Skip to main content
  1. Posts/

The tour of go をやって大事だと思ったとこだけメモ

·559 words·3 mins
Table of Contents

またtour of goをやったのでその中で覚えとこうと思ったとこだけメモりました。

本当にメモなので雑ですが。

いつのまにか全部日本語になっていて嬉しかったです。

目次

関数の引数は型が同じならまとめられる
#

func add(x, y int) int {
    return x + y
}

関数は複数の戻り値を返せる
#

戻り値に名前をつけられる.宣言までしてくれる(慣れるまで読みづらそう)
#

func split(sum int) (x, y int) {
    x = sum * 4 / 9
    y = sum - x
    return
}

var は:で省略できる
#

var a = 2
a := 2

printの仕方#

func main() {
    var i int
    var f float64
    var b bool
    var s string
    fmt.Printf("%v %v %v %q", i, f, b, s)
}

型変換は明示的にしなければならない
#

キャストしないとエラーになる

i := 42
f := float64(i)
u := uint(f)

constはnumeric 謎
#

forとifに()いらない
#

switch基本breakされる。したくなければfallthroughをcaseの最後につける
#

swichに条件式かける
#

deferはreturnの後に関数を呼ぶように予約することができる
#

defer へ渡した関数の引数は、すぐに評価されますが、その関数自体は呼び出し元の関数がreturnするまで実行されません。

複数deferはLIFO(last-in-first-out:最後に入れたのが最初に出る)で実行される
#

&がポインタへのキャスト が値へのキャスト と覚える。型宣言の時はintとなるので注意
#

配列
#

primes := [6]int{2, 3, 5, 7, 11, 13}
ve]

===========Slice始まり============

[]に長さ指定しなければSliceになる
#

var s []int = 配列[1:4]

sliceは配列への参照のようなもの
#

sliceを直接作ると配列を作ってからそれを参照するスライスを作成するようになっている

sliceを作る時配列全部入れたいならa[:]がいいかな
#

//以下の配列において
var a [10]int

//これらのスライス式は等価です:
a[0:10]
a[:10]
a[0:]
a[:]

len(slice)が長さ。cap(slice)はsliceの最初の要素から元となる配列の末尾までの長さ
#

slice nilでもlenとcapに0入る
#

ていうかnullじゃなくてnilなのか
#

makeでSliceの初期化
#

b := make([]int, 0, 5) // len(b)=0, cap(b)=5

SliceのSliceとかも作れる(二次元配列的な)
#

Sliceに要素をたすにはappend(slice,要素)
#

cap超えたら倍の配列を割り当て直す(Listと同じだね)
nilのsliceにも追加できる

===========slice終わり============

Range
#

var pow = []int{1, 2, 4, 8, 16, 32, 64, 128}
for i, v := range pow {
    fmt.Printf("2**%d = %d\n", i, v)
}
//iはインデックスvは要素のコピー

===========mapはじまり============

mapはDictionaryみたいなもん
#

tryGetしなくてもバグらない
#

v, ok := m["Answer"]

===========map終わり============

closureよくわかんねえけど気をつけよう
#

type hoge int で型を宣言できる。それにメソッドを持たせることもできる。
#

同じパッケージで宣言されている型にしかメソッド宣言できない。そりゃそうだ
#

goは常に値渡し
#

メソッドのレシーバーはポインタと型(?)で指定できる。インスタンスの内容を変更する場合はポインタじゃないとどうにもならない
#

メソッド基本的にポインタレシーバで宣言する!!
#

interfaceは明示的にimplementsしないでメソッドを実装しさえすればimplementsしてるとみなされる
#

interfaceのメソッドをポインタレシーバで実装したら参照を使わないとエラー出る。。。引っかかりそう
#

空のinterface{}はObjectみたいなもの
#

Type assertions 多分isからのasみたいなもん
#

var i interface{} = "hello"
s,ok := i.(string)
fmt.Println(s)

swichを使うと複数いける。あんま使って欲しくなさそう
#

switch v := i.(type) {
case T:
    // here v has type T
case S:
    // here v has type S
default:
    // no match; here v has the same type as i
}

Stringersインターフェース String()メソッドを実装するとstringとして出力できる?
#

Error() stringを実装すればerrorとして扱える
#

Channels
#

ch := make(chan int)
//みたいに宣言 chan int で多分型なので注意(初見だと読みづらい)

//こう使う
ch <- v    // v をチャネル ch へ送信する
v := <-ch  // ch から受信した変数を v へ割り当てる

//イメージ的にはキューにgoroutineを詰めてる感じ
//ch <-で詰めたgoroutineが全て終わらなければ <-ch は呼ばれない
//詰めたより多く<-chするとエラーが出る

バッファとしてもよく使いそうだな〜しんどい

package main

import (
    "fmt"
)

func fibonacci(n int, c chan int) {
    x, y := 0, 1
    for i := 0; i < n; i++ {
        c <- x
        x, y = y, x+y
    }
  //close しないとmain()のforで一生回るのでnull的なエラーが出る
    close(c)
}

func main() {
    c := make(chan int, 10)
    go fibonacci(cap(c), c)
    for i := range c {
        fmt.Println(i)
    }
}

Select
#

これは便利だ〜
channelが準備できるまで待って準備できたのから実行してくれる。複数準備できてたらランダム実行

package main

import "fmt"
import "time"


func fibonacci(c, quit chan int) {
    x, y := 0, 1
    for {
    time.Sleep(1 * time.Second) // 1秒待つ
        select {
        case c <- x:
            fmt.Println("case c")
            x, y = y, x+y
        case <-quit:
            fmt.Println("quit")
            return
        }
    }
}

func main() {
    c := make(chan int)
    quit := make(chan int)

    go func() {
        fmt.Println("func")
        for i := 0; i < 10; i++ {
            fmt.Println("funcの方",<-c)
        }
        quit <- 0
    }()
    fmt.Println("fibo前")
    fibonacci(c, quit)
}

こういう使い方もできるticktとafterhはchを返すんだね

package main

import (
    "fmt"
    "time"
)

func main() {
    tick := time.Tick(100 * time.Millisecond)
    boom := time.After(500 * time.Millisecond)
    for {
        select {
        case <-tick:
            fmt.Println("tick.%T",tick)
        case <-boom:
            fmt.Println("BOOM!")
            return
        default:
            fmt.Println("    .")
            time.Sleep(50 * time.Millisecond)
        }
    }
}

sync.Mutex
#

Lock して居るうちは他からアクセスできない

 

 

そのうち気が向けば綺麗にまとめたいね。

それにしてもgoroutineとかselectとかchannelとかは使いようによってはものすごく便利そうですね。

素敵。ではまた。

Related

いい人すぎるあなたがブラック企業をやめられない8つの理由に文句を言わせていくれ
·133 words·1 min
Vim:大文字小文字を入れ替える(便利)
·51 words·1 min
go言語 ピリオド三つってなんなの…?
·53 words·1 min