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>
SELECT文の評価順序メモ
たまに「どうだったっけ?」と忘れてしまう時があるので。
https://qiita.com/suzukito/items/edcd00e680186f2930a8 よりメモ
FROM ON JOIN WHERE GROUP BY HAVING SELECT DISTINCT ORDER BY TOP(LIMIT)
xmllintメモ
# 妥当性検証 xmllint --schema feed.xsd --noout feed.xml # 整形 xmllint --format feed.xml # インデントスペース4文字で整形 XMLLINT_INDENT=" " xmllint --format feed.xml
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() }