Go 構文
Hello world
package main import "fmt" // 最初に呼び出される func init() { fmt.Println("Init!") } func bazz() { fmt.Println("Bazz") } // 2番目に呼び出される func main() { // bazz() fmt.Println("Hello world!", "TEST TEST") }
パッケージ(import)
package main import ( "fmt" "os/user" "time" ) func main() { fmt.Println("Hello world!", time.Now()) fmt.Println(user.Current()) }
変数宣言
var
package main import "fmt" var ( i int = 1 f64 float64 = 1.2 s string = "test" t, f bool = true, false ) func foo() { // :=は関数の中でしか使用できない xi := 1 xi = 2 xf64 := 1.2 var xf32 float32 = 1.2 xs := "test" xt, xf := true, false fmt.Println(xi, xf64, xf32, xs, xt, xf) // Printfの"%T"で型を調べて出力することができる fmt.Printf("%T\n", xf32) fmt.Printf("%T\n", xi) } func main() { fmt.Println(i, f64, s, t, f) foo() }
for文
package main import "fmt" func main() { for i := 0; i < 10; i++ { if i == 3 { fmt.Println("continue") continue } if i > 5 { fmt.Println("break") break } fmt.Println(i) } sum := 1 for sum < 10 { sum += sum fmt.Println(sum) } fmt.Println(sum) }
defere
package main import "fmt" func foo() { defer fmt.Println("world foo") fmt.Println("hello foo") } func main() { /* foo() defer fmt.Println("world") fmt.Println("hello") */ fmt.Println("run") defer fmt.Println(1) defer fmt.Println(2) defer fmt.Println(3) fmt.Println("success") }
run success 3 2 1
スライス
func main() { n := []int{1, 2, 3, 4, 5, 6} fmt.Println(n) // [1 2 3 4 5 6] fmt.Println(n[2]) // 3 fmt.Println(n[2:4]) // [3 4] fmt.Println(n[:2]) // [1 2] fmt.Println(n[2:]) // [3 4 5 6] fmt.Println(n[:]) // [1 2 3 4 5 6] n[2] = 100 fmt.Println(n) // [ 1 2 100 4 5 6] var board = [][]int{ []int{0, 1, 2}, []int{3, 4, 5}, []int{6, 7, 8}, } fmt.Println(board) // [[0 1 2] [3 4 5] [6 7 8]] n = append(n, 100, 200, 300, 400) fmt.Println(n) // [1 2 100 4 5 6 100 200 300 400] }
make
func main() { // makeで初期化 make(型type, 長さlen, 容量cap) n := make([]int, 3, 5) fmt.Printf("len=%d cap=%d value=%v\n", len(n), cap(n), n) // len=3 cap=5 value=[0 0 0] n = append(n, 0, 0) fmt.Printf("len=%d cap=%d value=%v\n", len(n), cap(n), n) // len=5 cap=5 value=[0 0 0 0 0] // スライスのため追加できる n = append(n, 1, 2, 3, 4, 5) fmt.Printf("len=%d cap=%d value=%v\n", len(n), cap(n), n) // len=10 cap=10 value=[0 0 0 0 0 1 2 3 4 5] // 引数を一つにすると長さも容量も同じになる a := make([]int, 3) fmt.Printf("len=%d cap=%d value=%v\n", len(a), cap(a), a) // len=3 cap=3 value=[0 0 0] // 0のスライスをメモリに確保する b := make([]int, 0) // メモリに確保しない var c []int fmt.Printf("len=%d cap=%d value=%v\n", len(b), cap(b), b) // len=0 cap=0 value=[] fmt.Printf("len=%d cap=%d value=%v\n", len(c), cap(c), c) // len=0 cap=0 value=[] c = make([]int, 5) for i := 0; i < 5; i++ { c = append(c, i) fmt.Println(c) // [0] [0 0] [0 0 0] [0 0 0 0] [0 0 0 0 0] [0 0 0 0 0 0] [0 0 0 0 0 0 1] [0 0 0 0 0 0 1 2] [0 0 0 0 0 0 1 2 3] [0 0 0 0 0 0 1 2 3 4] } fmt.Println(c) // [0 0 0 0 0 0 1 2 3 4] var d []int d = make([]int, 0, 5) for i := 0; i < 5; i++ { d = append(d, i) fmt.Println(d) // [0] [0 1] [0 1 2] [0 1 2 3] [0 1 2 3 4] } fmt.Println(d) // [0 1 2 3 4] }
map
func main() { m := map[string]int{"apple": 100, "banana": 200} fmt.Println(m) // map[apple:100 banana:200] fmt.Println(m["apple"]) // 100 m["banana"] = 300 fmt.Println(m) // map[apple:100 banana:300] // 新しい要素を追加 m["new"] = 500 fmt.Println(m) // map[apple:100 banana:300 new:500] // 存在しない値を取り出すと fmt.Println(m["nothing"]) // 0 // 値の確認 v, ok := m["apple"] fmt.Println(v, ok) // 100 true // 存在しない値を確認すると v2, ok2 := m["nothing"] fmt.Println(v2, ok2) // 0 false // mapは返り値を無視することができる v := m["apple"] fmt.Println(v) // 100 true // keyがstring、valueがintのmapを初期化 // メモリ上に空のマップを作成 m2 := make(map[string]int) m2["pc"] = 5000 fmt.Println(m2) // map[pc:5000] // メモリ上に入れるマップがないためpanicになる // マップを初期化していない状態(nil)で値をセットするとpanicになる var m3 map[string]int m3["pc"] = 5000 fmt.Println(m3) // panic: assignment to entry in nil map // varで宣言した場合はnilになる(スライスでもマップの場合でも) var s []int if s == nil { fmt.Println("Nil") // Nil } }
関数
func add(x, y int) (int, int) { return x + y, x - y } func cal(price, item int) (result int) { result = price * item return } func main() { r1, r2 := add(10, 20) fmt.Println(r1, r2) // 30 -10 r3 := cal(100, 2) fmt.Println(r3) // 200 f := func(x int) { fmt.Println("inner func", 1) } f(1) // inner func 1 // 省略記法 func(x int) { fmt.Println("inner func", 1) }(1) // inner func 1 }
ポインタ
package main import "fmt" func main() { var p *int fmt.Println(p == nil) // true 定義のみを行ったポインタ型の変数の初期値はnilになり、参照型と同じ様に振る舞う }
func Double(i int) { i = i * 2 } func main() { var n int = 100 Double(n) fmt.Println(n) // 100 }
0xc000b4008番地 100 変数n(実引数) ↓値渡しでは変数の値をコピーする 0x999b11111番地 100 変数i(仮引数) ↓この後Double関数が実行され、変数iの値が変更される 0x999b11111番地 200 変数i ↓値渡しのため変数nには反映されない(仮引数を変更しても、実引数には反映されない) fmt.Println(n) // 100
package main import "fmt" func main() { var p *int fmt.Println(p == nil) // true 定義のみを行ったポインタ型の変数の初期値はnilになり、参照型と同じ様に振る舞う }
json
import "encoding/json"
encoding/jsonパッケージはRFC4627に準拠したJSONエンコーディングを処理するエンコーダーとデコーダーの機能を提供
構造体型からJSONテキストへの変換
関数json.Marshalは、任意の構造体型からJSONテキストへのエンコード処理を実行する 内部的にreflectパッケージのリフレクション機能が使用されており、特別な設定をせずとも構造体型に定義されたフィールド名と値の組み合わせから自動的にJSONテキストを生成する
json.Marshalの戻り値は[]byte型のため、テキストとして確認する場合はstring(bs)のように文字列へ変換する必要がある また、出力されるJSONテキストのキーを構造体フィールド名ではなく、任意の名前にマッピングしたい場合は構造体の「タグ」を利用できる
gorilla/mux
func getArticle(w http.ResponseWriter, r *http.Request) { // Vars関数でパラメータの値を取得 // get http://localhost:8000/articles/1 -> 1を取得 params := mux.Vars(r) fmt.Println(params) // map[id:1] // reflect 動的に型を扱いたい場合に便利なパッケージ // typeof 型確認 fmt.Println(reflect.TypeOf(params["id"])) // string // Convert Type from String -> Int // Not handling err -> _ i, _ := strconv.Atoi(params["id"]) // URLに指定したIDの情報を取得 for _, article := range articles { if article.ID == i { json.NewEncoder(w).Encode(&article) } } }