コピペコードで快適生活

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

aws-cliで複数のプロファイル設定を持つ

複数のAWSアカウントを扱うことになったので、aws-cliのプロファイルの使い方をメモしておく。

# 設定やプロファイル一覧を見る
cat ~/.aws/config
cat ~/.aws/credentials

# デフォルトの設定をする
aws configure
AWS Access Key ID [None]: xxx
AWS Secret Access Key [None]: xxx
Default region name [None]: ap-northeast-1
Default output format [None]: json

# プロファイルの設定をする
aws configure --profile user1
AWS Access Key ID [None]: xxx
AWS Secret Access Key [None]: xxx
Default region name [None]: ap-northeast-1
Default output format [None]: json

# 現在使用しているプロファイルの確認
aws configure list

# 指定のプロファイルの確認
aws configure list --profile user1

# 一時的にプロファイルを切り替えて実行
aws s3 ls --profile user1

# デフォルト変更
export AWS_PROFILE=user1
aws configure list

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()
}

チャネルを使ってゴルーチン間でやりとりする

package main

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

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

	// stringを扱うチャネルを作成
	// これでゴルーチン間のメッセージのやり取りができる
	statusChan := make(chan string)

	for _, url := range urls {
		go func(url string) {
			res, err := http.Get(url)
			if err != nil {
				log.Fatal(err)
			}
			defer res.Body.Close()

			// 結果をチャネルに書き込む
			statusChan <- res.Status
		}(url)
	}

	for i := 0; i < len(urls); i++ {
		// チャネルからstringを読み出す
		// 書き込みがされるまで待つ
		fmt.Println(<-statusChan)
	}
}

チャネルを返す関数に切り出す版

package main

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

//
// 関数でチャネルを作成
//
func getStatus(urls []string) <-chan string {
	statusChan := make(chan string)
	for _, url := range urls {
		go func(url string) {
			res, err := http.Get(url)
			if err != nil {
				log.Fatal(err)
			}
			defer res.Body.Close()
			statusChan <- res.Status
		}(url)
	}
	// チャネルを返す
	return statusChan
}

func main() {
	urls := []string{
		"https://www.example.com",
		"https://www.example.co.jp",
		"https://www.example.com/",
		"https://www.example.com/jp/",
	}
	statusChan := getStatus(urls)

	for i := 0; i < len(urls); i++ {
		fmt.Println(<-statusChan)
	}
}

select文を用いたイベント制御

package main

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

//
// 関数でチャネルを作成
//
func getStatus(urls []string) <-chan string {
	statusChan := make(chan string)
	for _, url := range urls {
		go func(url string) {
			res, err := http.Get(url)
			if err != nil {
				log.Fatal(err)
			}
			defer res.Body.Close()
			statusChan <- res.Status
		}(url)
	}
	// チャネルを返す
	return statusChan
}

//
// select文を用いたイベント制御
//
func selectFunc() {
	// 1秒後に値が読み出せるチャネル
	timeout := time.After(time.Second)
	urls := []string{
		"https://www.example.com",
		"https://www.example.co.jp",
		"https://www.example.com/",
		"https://www.example.com/jp/",
	}
	statusChan := getStatus(urls)

LOOP: // 任意のラベル名を指定
	for {
		// selectのcaseに指定すると
		// いずれかのcaseの操作が行われたときに
		// 該当する処理が実行される
		// caseが実行されるまで後の処理は待つ
		select {
		case status := <-statusChan:
			// 受信データを表示
			fmt.Println(status)
		case <- timeout:
			// このfor/selectを抜ける
			// breakだけだとselectだけ抜けるためラベルを指定
			break LOOP
		}
	}
}


func main() {
	selectFunc()
}

同時期同数制御

チャネルバッファを使って、ゴルーチンの同時期同数を制御する。

package main

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

// サイズ0の構造体
// limitチャネルに入ればなんでもいい
var empty struct{}

func getStatus(urls []string) <-chan string {
	statusChan := make(chan string, 3)

	// バッファを5にして生成
	limit := make(chan struct{}, 5)
	go func() {
		for _, url := range urls {
			select {
			case limit <- empty:
				// limitに書き込みが可能な場合は取得処理を実施
				go func(url string) {
					// このゴルーチンは同時に5つしか起動しない
					res, err := http.Get(url)
					if err != nil {
						log.Fatal(err)
					}
					statusChan <- res.Status
					// 終わったら1つ読み出して空きを作る
					<-limit
				}(url)
			}
		}
	}()

	return statusChan
}

func main() {
	urls := []string{
		"https://example.com",
		"https://example.com",
		"https://example.com",
		"https://example.com",
		"https://example.com",
		"https://example.com",
	}
	statusChan := getStatus(urls)

	for i := 0; i < len(urls); i++ {
		fmt.Println(<-statusChan)
	}
}

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()
}