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

サーバサイド Go 入門資料 まとめ · GitHub

future-architect.github.iofuture-architect.github.io