Skip to content

Instantly share code, notes, and snippets.

@non117 non117/snipet.md
Last active Feb 21, 2016

Embed
What would you like to do?
golangお勉強

ifのよくあるパターン

break, continue, goto, returnで抜ける

f, err := os.Open(name)
if err != nil {
    return err
}
d, err := f.Stat()
if err != nil {
    return err
}
codeUsing(f, d)

for

// Cのwhileに相当する形式
for condition { }

// Cのfor(;;)に相当する形式
for { }

// range
var m map[string]int
sum := 0
for _, value := range m {  // キーは使われません
    sum += value
}

switch

func unhex(c byte) byte {
    switch {
    case '0' <= c && c <= '9':
        return c - '0'
    case 'a' <= c && c <= 'f':
        return c - 'a' + 10
    case 'A' <= c && c <= 'F':
        return c - 'A' + 10
    }
    return 0
}

func shouldEscape(c byte) bool {
    switch c {
    case ' ', '?', '&', '=', '#', '+', '%':
        return true
    }
    return false
}

戻り値のパラメータはreturnで省略できる

func ReadFull(r Reader, buf []byte) (n int, err os.Error) {
    for len(buf) > 0 && err == nil {
        var nr int
        nr, err = r.Read(buf)
        n += nr
        buf = buf[nr:len(buf)]
    }
    return
}

defer

returnするときの処理を予約

// Contentsは、ファイルの内容を文字列として返します。
func Contents(filename string) (string, os.Error) {
    f, err := os.Open(filename)
    if err != nil {
        return "", err
    }
    defer f.Close()  // f.Closeは、完了時に実行される

    var result []byte
    buf := make([]byte, 100)
    for {
        n, err := f.Read(buf[0:])
        rresult = append(result, buf[0:n]...) // appendについては後述します。
        if err != nil {
            if err == os.EOF {
                break
            }
            return "", err  // ここでリターンしたときに、fはクローズされる
        }
    }
    return string(result), nil // ここでリターンしたときに、fはクローズされる
}

new, コンストラクタ, make

  • new はゼロ値で埋めたオブジェクトのポインタを返す
  • make はスライス, マップ, チャネルだけに使える
// コンストラクタの例
return &File{fd, name, nil, 0}

// makeの例, 型, 長さ, キャパシティ
make([]int, 10, 100)

スライスとは何か

http://jxck.hatenablog.com/entry/golang-slice-internals

  • 配列は関数に渡すと値渡し
  • 配列の長さは変更できない
  • スライスは配列をラップしている
  • スライスは可変長配列のように使える
  • スライスは参照型
  • なので関数に渡しても参照が渡る
arr := []int{1, 2, 3, 4}
arr := make([]int, 4)
arr[0] = 1
arr[1] = 2
arr[2] = 3
arr[3] = 4
arr[4] = 5 // index out of range
arr = append(arr, 5)
arr = append(arr, 6)
  • 宣言時の arr はどちら長さ4の配列への参照
  • そのままでは arr[4] へ代入することはできない
  • append は倍の長さの配列を確保してそこにコピーする
  • appendした後の cap(arr) はキャパシティ8
  • なので, たくさん詰める時はmakeするときにcapを指定しておくと良い
arr := make([]int, 0, 5)
  • makeの第二引数が0なのは, 詰める値を初期化しないため
  • appendするのか添字アクセスするか変わってくる
  • var arr []intはlen=0, cap=0
// スライス連結の例
func Merge3(a, b []int) []int {
    return append(a, b...)
}
func del(a []int, i int) []int {
    copy(a[i:], a[i+1:])
    a = a[:len(a)-1]
    return a
}

func main() {
    a := []int{1, 2, 3, 4, 5}
    a = del(a, 2)
    log.Println(a, len(a), cap(a)) // [1 2 4 5] 4 5
}

// []int    *
//          |
// [5]int  [1, 2, 4, 5, 5]
log.Println(a[:cap(a)])
  • delでスライスから削除しても実体の配列には値が残ってGCされないケースがある
var zero int // ゼロ値
func del(a []int, i int) []int {
    copy(a[i:], a[i+1:])
    a[len(a)-1] = zero // ゼロ値, nil の代入
    a = a[:len(a)-1]
    return a
}
  • ちゃんとゼロ値を代入しましょう

map

var timeZone = map[string] int {
    "UTC":  0*60*60,
    "EST": -5*60*60,
    "CST": -6*60*60,
    "MST": -7*60*60,
    "PST": -8*60*60,
}
  • 存在しないキーが与えられたら, valueのゼロ値が返る
func offset(tz string) int {
    if seconds, ok := timeZone[tz]; ok {
        return seconds
    }
    log.Println("unknown time zone:", tz)
    return 0
}
  • ゼロ値とキーの存在を区別したいパターンは上記

出力

fmt.Printf("Hello %d\n", 23)
fmt.Fprint(os.Stdout, "Hello ", 23, "\n")
fmt.Println("Hello", 23)
fmt.Println(fmt.Sprint("Hello ", 23))
  • %v が万能?で便利なフォーマット指定
  • %+v&{a:7 b:-2.35 c:abc def}のように構造体のフィールド名が
  • %#v&main.T{a:7, b:-2.35, c:"abc\tdef"}のように型情報も出力される
  • %Tで型情報を出力
func (t *T) String() string {
    return fmt.Sprintf("%d/%g/%q", t.a, t.b, t.c)
}
  • String() stringのメソッドを定義するとデフォルトフォーマットを定義
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.