コピペコードで快適生活

明日使えるソースを自分のために

Goことはじめ(並列処理)

http://gihyo.jp/dev/feature/01/go_4beginners/0005?page=1
より学んだことメモ。

package main

import (
	"fmt"
	"log"
	"net/http"
	"sync"
)

func main() {
	wait := new(sync.WaitGroup)

	urls := []string{
		"https://www.example.com",
		"https://www.example.co.jp",
		"https://www.example.com/",
		"https://www.example.com/jp/",
	}

	for _, url := range urls {
		// waitGroup に追加(カウントを増やす)
		wait.Add(1)

		// 取得処理をゴルーチン(軽量スレッド)で実行
		// goと書くことで、並列に処理を実行できる
		go func(url string) {
			res, err := http.Get(url)
			if err != nil {
				log.Fatal(err)
			}
			defer res.Body.Close()
			fmt.Println(url, res.Status)

			// waitGroupから削除(カウントを減らす)
			wait.Done()
		}(url)
	}

	// カウントが0になるまで待つ
	wait.Wait()
}

Goことはじめ(net/httpパッケージ)

http://gihyo.jp/dev/feature/01/go_4beginners/0004?page=3
より学んだことメモ。

hello worldを返すだけのhttpサーバ

package main

import (
	"fmt"
	"net/http"
)

//
// http.ResponseWriterがレスポンスデータ
// *http.Requestはリクエストデータ
//
func IndexHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprint(w, "hello world")
}

func main() {
	// ルーティング設定
	http.HandleFunc("/", IndexHandler)

	// ポートを割り当ててサーバ起動
	http.ListenAndServe(":3000", nil)
}

JSONをPOSTでうけてファイルに保存する

package main

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"os"
)

type Person struct {
	ID int `json:"id"`
	Name string `json:"name"`
}

//
// http.ResponseWriterがレスポンスデータ
// *http.Requestはリクエストデータ
//
func IndexHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprint(w, "hello world")
}

func PersonHandler(w http.ResponseWriter, r *http.Request) {
	defer r.Body.Close() // 処理の最後にBodyを閉じる

	if r.Method == "POST" {
		// リクエストボディをJSONに変換
		var person Person
		decoder := json.NewDecoder(r.Body)
		err := decoder.Decode(&person)
		if err != nil { // エラー処理
			log.Fatal(err)
		}

		// ファイル名を {id}.txt とする
		filename := fmt.Sprintf("%d.txt", person.ID)
		file, err := os.Create(filename) // ファイルを生成
		if err != nil {
			log.Fatal(err)
		}
		defer file.Close()

		// ファイルにNameを書き込む
		_, err = file.WriteString(person.Name)
		if err != nil {
			log.Fatal(err)
		}

		// レスポンスデータとしてステータスコード201を返す
		w.WriteHeader(http.StatusCreated)
	}
}

func main() {
	// ルーティング設定
	http.HandleFunc("/", IndexHandler)
	http.HandleFunc("/persons", PersonHandler)

	// ポートを割り当ててサーバ起動
	http.ListenAndServe(":3000", nil)
}

GETでうけてtemplateを使ってHTMLを返す

package main

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"os"
	"strconv"
	"html/template"
	"io/ioutil"
)

type Person struct {
	ID int `json:"id"`
	Name string `json:"name"`
}

// テンプレートのコンパイル
// Mustを使うとエラー時にパニックを起こす
// var t, err := template.personFiles("index.html")
var t = template.Must(template.ParseFiles("index.html"))

//
// http.ResponseWriterがレスポンスデータ
// *http.Requestはリクエストデータ
//
func IndexHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprint(w, "hello world")
}

func PersonHandler(w http.ResponseWriter, r *http.Request) {
	defer r.Body.Close() // 処理の最後にBodyを閉じる

	if r.Method == "POST" {
		// リクエストボディをJSONに変換
		var person Person
		decoder := json.NewDecoder(r.Body)
		err := decoder.Decode(&person)
		if err != nil { // エラー処理
			log.Fatal(err)
		}

		// ファイル名を {id}.txt とする
		filename := fmt.Sprintf("%d.txt", person.ID)
		file, err := os.Create(filename) // ファイルを生成
		if err != nil {
			log.Fatal(err)
		}
		defer file.Close()

		// ファイルにNameを書き込む
		_, err = file.WriteString(person.Name)
		if err != nil {
			log.Fatal(err)
		}

		// レスポンスデータとしてステータスコード201を返す
		w.WriteHeader(http.StatusCreated)
	} else if r.Method == "GET" {
		// パラメータを取得
		id, err := strconv.Atoi(r.URL.Query().Get("id"))
		if err != nil {
			log.Fatal(err)
		}

		filename := fmt.Sprintf("%d.txt", id)
		b, err := ioutil.ReadFile(filename)
		if err != nil {
			log.Fatal(err)
		}

		// personを生成
		person := Person {
			ID: id,
			Name: string(b),
		}

		// レスポンスにエンコーディングしたHTMLを書き込む
		t.Execute(w, person)
	}
}

func main() {
	// ルーティング設定
	http.HandleFunc("/", IndexHandler)
	http.HandleFunc("/persons", PersonHandler)

	// ポートを割り当ててサーバ起動
	http.ListenAndServe(":3000", nil)
}

データを埋め込むには{{ }}で値をくくり,その中に埋め込みたいプロパティを指定する。

<!DOCTYPE html>
<title>person</title>
<h1>{{ .ID }} : {{ .Name }}</h1>

Goことはじめ(ファイルのRead/Write)

http://gihyo.jp/dev/feature/01/go_4beginners/0004?page=2
より学んだことメモ

package main

import (
	"fmt"
	"log"
	"os"
)

//
// ファイルの書き込み
//
func FileWriteFunc() {
	fmt.Println("ファイルの書き込み --------- ")

	// ファイルを生成
	file, err := os.Create("./file.txt")
	if err != nil {
		log.Fatal(err)
	}

	// 終了時にファイルを閉じる
	defer file.Close()

	// 書き込むデータを[]byteで用意する
	message := []byte("hello world\n")

	// Write()を用いて書き込む
	_, err = file.Write(message)
	if err != nil { // エラー処理
		 log.Fatal(err)
	}

	// 直接文字列を渡す版1
	// _, err = file.WriteString("hello world\n")

	// 直接文字列を渡す版2
	// _, err = fmt.Fprint(file, "hello world\n")
}

//
// ファイルの読み込み
//
func FileReadFunc() {
	fmt.Println("ファイルの読み込み --------- ")

	// ファイルを開く
	file, err := os.Open("./file.txt")
	if err != nil { // エラー処理
		log.Fatal(err)
	}

	// プログラムが終わったらファイルを閉じる
	defer file.Close()

	// 12byte格納可能なスライスを用意する
	message := make([]byte, 12)

	// ファイル内のデータをスライスに読み出す
	// io.Reader インターフェースを使う
        // type Reader interface {
        //     Read(p []byte) (n int, err error)
        // }
	_, err = file.Read(message)
	if err != nil {
		log.Fatal(err)
	}

	// ファイルの中身をすべて読み出す
	// ioutil.ReadAllを使えば、事前にbyte列を準備する必要はない
	// file, _ := os.Open("./file.txt")
	// message, err := ioutil.ReadAll(file)

	// 文字列にして表示
	fmt.Print(string(message))
}

func main() {
	FileWriteFunc()
	FileReadFunc()
}

JSONのEncoder/Decoder経由の保存

package main

import (
	"fmt"
	"log"
	"os"
	"encoding/json"
)

type Person struct {
	ID int `json:"id"`
	Name string `json:"name"`
	Email string `json:"-"`
	Age int `json:"age"`
	Address string `json:"address,omitempty"`
	memo string
}

//
// JSONの書き出し
//
func JsonWriteFunc() {
	fmt.Println("JSONの書き出し ---------- ")

	person := &Person{
		ID: 1,
		Name: "Hogeo",
		Email: "hogeo@example.com",
		Age: 20,
		Address: "",
		memo: "TestUser",
	}

	// ファイルを開く
	file, err := os.Create("./person.json")
	if err != nil {
		log.Fatal(err)
	}
	defer file.Close()

	// エンコーダの取得
	encoder := json.NewEncoder(file)

	// JSONエンコードしたデータの書き込み
	// byte[]に変換しなくても直接構造体を渡せる
	err = encoder.Encode(person)
	if err != nil {
		log.Fatal(err)
	}
}

//
// JSONの読み込み
//
func JsonReadFunc() {
	fmt.Println("JSONの読み込み ---------- ")

	// ファイルを開く
	file, err := os.Open("./person.json")
	if err != nil {
		log.Fatal(err)
	}
	defer file.Close()

	// データを書き込む変数
	var person Person

	// デコーダの取得
	decoder := json.NewDecoder(file)

	// JSONデコードしたデータの読み込み
	// JSONフォーマットに誤りがあればエラー
	// 構造体にないフィールドは無視される
	err = decoder.Decode(&person)
	if err != nil {
		log.Fatal(err)
	}

	// 読み出した結果の表示
	fmt.Println(person)
}

func main() {
	JsonWriteFunc()
	JsonReadFunc()
}

ioutls使うと便利

http://gihyo.jp/dev/feature/01/go_4beginners/0004?page=3

package main

import (
	"fmt"
	"io/ioutil"
	"log"
)

//
// ファイルの操作は、
// io/ioutilsパッケージを使うとより簡単にできる
//
func main() {
	hello := []byte("hello world\n")

	// ファイルにメッセージを書き込む
	// 第2引数にバイト列、第3引数にパーミッション
	err := ioutil.WriteFile("./file.txt", hello, 0666)
	if err != nil {
		log.Fatal(err)
	}

	// ファイルの中身を全て読みだす
	message, err := ioutil.ReadFile("./file.txt")
	if err != nil {
		log.Fatal(err)
	}
	fmt.Print(string(message))
}

Goことはじめ(JSONの取り扱い)

http://gihyo.jp/dev/feature/01/go_4beginners/0004 より学んだことメモ

package main

import (
	"fmt"
	"log"
	"encoding/json"
)

//
// 構造体にタグをつけることでJSON変換時の
// ルールを定義することができる
// 何も指定しない場合はpublicなフィールドだけ格納される
//
type Person struct {
	ID int `json:"id"` // id という名前で格納する
	Name string `json:"name"`
	Email string `json:"-"` // JSONに格納しない
	Age int `json:"age"`
	Address string `json:"address,omitempty"` // ,omitemptyで値が空なら無視
	memo string
}
// JSONへの変換
func JsonStringifyFunc() {
	fmt.Println("構造体からJSONへの変換 ---------- ")
	person := &Person {
		ID: 1,
		Name: "Gopher",
		Email: "gopher@example.org",
		Age: 5,
		Address: "",
		memo: "golang lover",
	}
	// 構造体にデータを代入して
	// ポインタを渡すだけで、
	// デフォルトフォーマットでJSON文字列の[]byteを生成できる
	b, err := json.Marshal(person)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(string(b))  // 文字列に変換
	// -> {"id":1,"name":"Gopher","age":5}
}
// JSONから構造体への変換
func JsonParseFunc() {
	fmt.Println("JSONから構造体への変換 ---------- ")
	var person Person
	b := []byte(`{"id":1,"name":"Hogeo","age":10}`)
	err := json.Unmarshal(b, &person)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(person)
}

func main() {
	JsonStringifyFunc()
	JsonParseFunc()
}

goenvインストールメモ

# インストール
$ git clone https://github.com/syndbg/goenv.git ~/.goenv

# ~/.bash_profile に追記
export GOENV_ROOT="$HOME/.goenv"
export PATH="$GOENV_ROOT/bin:$PATH"
eval "$(goenv init -)"

# 反映
source ~/.bash_profile

# 使えるバージョン確認
goenv install -l

# 指定バージョンをインストール
goenv install 1.12.3

# グローバルで使う
goenv global 1.12.3

# そのディレクリ以下で使う
goenv local 1.12.3

# depのインストール
# npmみたいにパッケージをプロジェクトディレクトリ内にインストールできるようにするやつ
go get -u github.com/golang/dep/cmd/dep

# goenvの更新
cd $(goenv root)
git pull