Goの勉強 関数

Goの勉強をやり始めたのでメモ。
プログラミング言語 Go」を読んでる。

宣言

func name(parameter-list) (result-list) {  
        body  
}  

パラメータと同様に返り値にも名前を付けることができる
その場合は返り値の名前のローカル変数が作られる

func pi() (pi float64) {  
    pi = math.Pi // 宣言なしで変数 pi を使える  
    return  
}  

パラメータを使用しない場合、 _ を使うか、名前を省略できる

func zero(int, int) int {  
    return 0  
}  

func zero2(_ int, _ int) int {  
    return 0  
}  
  • Go にはデフォルト値や名前付き引数はない
  • 引数は値渡しされる(コピーを受け取る)が、間接的に参照されているものは影響を受ける可能性がある
  • 実装がない関数は Go 以外で実装されている

複数戻り値

複数戻り値はそのまま複数パラメータとして使用できる

func findLinks(url string) ([]string, error) {  
}  

log.Println(findLinks(url))  

戻り値にうまく名前付けをすることができれば、関数の結果の意味をドキュメント化することができる

func Size(rect image.Rectangle) (width, height int)  

エラー

  • Go にも例外機構はあるが、バグであることを示す本当に予期されていないエラーを報告するために使われ、予期されるエラーには使用されない
  • 関数がエラーを返した場合、エラーに対して対応するのは呼び出し元の責任である
  • エラーメッセージは連鎖されることが多いので、先頭を大文字にしたり改行を入れるべきではない
  • ファイル読み込み時にこれ以上入力がない場合にEOFがエラーとして返される

関数値

関数は他のプログラミング言語と同様に関数を変数に入れることができる

func square(n int) {  
        return n * n  
}  

f := square  
fmt.Println(f(3))  
  • 関数型はシグネチャで判断される。つまり func(int)func(int, int) は別の型
  • 関数型は nil と比較できるが、他の値とは比較可能ではない

無名関数

名前付き関数はパッケージレベルでだけ宣言できるが、関数リテラルはすべての式内で使用できる

strings.Map(func(r rune) rune { return r + 1 }, "HAL-9000")  

無名関数の外側の変数を参照できる。

func squares() func() int {  
        var x int  
        return func() int {  
                x++  
                return x * x  
        }  
}  

無名関数を再帰的に呼び出すためには、先に変数を定義し、その後に代入する必要がある。

無名関数はその瞬間の変数の値を補足するのではなく、変数自体を補足するので注意。

funcs []func()  
for _, item := range items {  
        funcs = append(funcs, func() string { return item })  
}  

for _, action := range funcs {  
    fmt.Println(action())  
}  

この場合、 items の最後の要素がずらずらと並ぶだけである。

可変個引数

  • 可変個引数はスライスで渡ってくる。
    • ただし、シグネチャとしては可変個引数とスライスは違う。

遅延関数呼び出し

  • defer を使用すると、その文は return のタイミングで呼ばれるようになる。

パニック・リカバー

  • panic を使用することで、システムをクラッシュさせることができる。
  • panic が使用されると、クラッシュされる前に遅延呼び出しが行われる。
  • recover を使用するとパニック状態を解消できる。
    • 一般的な規則として、他のパッケージのパニックからの回復を試みるべきでない。

Goの勉強 コンポジット型

Goの勉強をやり始めたのでメモ。
プログラミング言語 Go」を読んでる。

配列

  • 固定長で型が同じ必要がある
  • 以下のように宣言できる

      var a [5]int  
      var b [5]int{1, 2, 3, 4, 5}  
      var c [...]int{1, 2, 3, 4, 5}  
      var d [...]int{99: -1}  
    
  • 初期値がない場合はそれぞれの要素にゼロ値が適用される
  • == で比較可能
  • 関数の引数として配列を渡すと、参照ではなくコピーが渡される

スライス

  • 可変長で型が同じ必要がある
  • スライスにはポインタ、長さ、容量がある
  • 配列の部分配列みたいなもの
    • スライスには基底配列がある
    • 以下のようにスライスを生成すると同じサイズの基底配列が自動的に生成される

      s := []int{0, 1, 2, 3, 4, 5}  
      
  • スライスは == で比較不可能
    • slice == nil のみ比較可能
      • ただし、空かどうかを調べたい場合は len(slice) == 0 を使う
  • スライスのゼロ値は nil
  • make を使用すると型、長さ、容量を指定してスライスを生成できる
  • append を使うことでスライスに値を追加できる
    • append した結果の基底配列が、元のスライスの基底配列と同じかどうかはわからない

マップ

  • ハッシュテーブル
  • キーと値はそれぞれで型を指定する必要がある
  • キーの型は == で比較可能でなければならない
    • 精度や NaN があることから、 float 系をキーで使うことは推奨されない
  • 以下のように作成できる

    go m := make(map[string]int) var m map[string]int{ "taro": 11, "jiro": 8, }

  • delete を使用して要素を削除できる
  • 存在しないキーにアクセスするとゼロ値が返る
  • マップに要素が存在するかについては以下のようにチェックする

      item, ok := m["saburo"]  
      if !ok {  
          // ...  
      }  
    
  • マップの要素のアドレスを取得することはできない
  • マップをループした際の取得順はランダムになる

構造体

type Student struct {  
    ID   int  
    Name string  
}  

のように宣言できる。

  • 名前付き構造体は自身のフィールドに同じ型のフィールドを持てない
    • 持ちたい場合は自身の型のポインタを使う
  • 空構造体 struct{} を使う人もいるが、筆者はあまり好きではないらしい
  • すべてのフィールドが比較可能であれば、構造体も比較可能である
    • よって、マップのキーに構造体を指定することもできる
  • 無名フィールドを使うことで、ネストされた構造体でも短いドットでアクセスできる
    • デリゲーションみたいなイメージ?
    • ただし、本当に無名ではなく、暗黙的に無名フィールドの型名と同じ名前が割り当てられている
  • フィールドタグを付けることで、メタデータを付与することができる

      type Movie struct {  
          Year int `json:"released"`  
      }  
    
    • 慣習的に key:"value"の形式で書く
    • JavaDocみたいな感じかな

テンプレート

  • テキストテンプレートを使うことで文字列に変数を埋め込むことができる

      const templ = `合計{{.TotalCount}}件  
      ---  
      {{range .Items}}  
      ID: {{.ID}}  
      Title: {{.Title}}  
      {{end}}  
      `  
      text, err := template.New("text").Parse(templ)  
      err := text.Execute(os.Stdoutm items)  
    
    • {{.}} で現在の要素のアクセスできる
    • {{range}} {{end}} でループ
    • めちゃくちゃ使いづらい
      • JSやPHPに比べると面倒
      • IDEが補完してくれない
  • HTMLテンプレートを使うことでエスケープをしつつ文字列に変数を埋め込むことができる
    • 変数の型を template.HTML にすることで、エスケープなしで出力することができる

Goの勉強 基本データ型

Goの勉強をやり始めたのでメモ。
プログラミング言語 Go」を読んでる。

整数

  • Goの整数には符号付き、符号なしがある。
  • runeint32 の同類語で、 byteint8 の同類語
    • runeUnicodeのコードポイントであることを強調し、 byte は生データであることを強調する。
  • uintptr はポインタの値のすべてのビットを保持する。

浮動小数点数

  • ゼロ除算の結果は NaN になる。
  • NaN == NaNfalse になる。

複素数

仕事では使わなさそう。

ブーリアン

JSのような以下のコードは書けない。

fmt.Print(1 || 0)  
// invalid operation: operator || not defined on 1 (untyped int constant)  
// JSの場合は 1 が返る  

文字列

  • 文字列はスライスのようにアクセスできるが、何バイト目であるかであって何文字目かではない。
  • 文字列連結は + を使う。(どこかの言語のように . で繋げない)
  • "s" は文字列リテラルで、エスケープシーケンスが使える。
  • `s` は生文字リテラルで、エスケープシーケンスが使えない。

定数

  • 定数はコンパイル時に評価できる値
  • const宣言では iota が使える。 iota はゼロから始まり、順番に個々の項目ごとに1増加する。

Goの勉強 プログラム構造

Goの勉強をやり始めたのでメモ。
プログラミング言語 Go」を読んでる。

名前

  • 大文字と小文字は区別される。
  • 予約語と事前宣言がある。 trueやintは事前宣言なので、宣言で使うことができる。
  • キャメルケースで書く

ポインタ

ポインタはアドレスを指す。
以下のようなコードも安全

var p = f()  

func f() *int {  
  v := 1  
  return &v  
}

f() を呼び出した後も引き続きローカル変数 v のアドレスが参照され、 v も破棄されない。

タプル代入

x, y = y, x  

のようなことができる。

型宣言

type PersonName string  

のようにして型を作ることができる。

name := PersonName("たなか")  

のように型変換を行うことでその型のインスタンスを作れる。

パッケージ初期化

init 関数を使うことでそのファイルのプログラム開始時の挙動を設定できる。
init 関数は呼び出すことも参照することもできない。

Goの勉強 チュートリアル

Goの勉強をやり始めたのでメモ。
プログラミング言語 Go」を読んでる。

インストール

公式サイトからインストールできる。
前にやったときはインストーラなんてなかった気がするけど、最近はあるみたい。

GOPATH, ROOTPATH

よくわかってないけどGoLandの場合は設定すると動かなくなる。

フォーマット

とりあえず gofmtgoimports を設定しとけば良さそう。
GoLandではFileWatchers で設定できる。

変数

var s string  
s := ""  

のように書く。
初期値を設定しなかった場合はゼロ値が入るので、上の2つは同じ意味。

定数

const (  
    seconds  = 60  
    minutues = 60  
    hours    = 24  
)  

のように書く。コンパイル時に値が確定しているものを定数として扱う。

条件分岐

if

if a > 0 {  
}  

また、変数宣言なども同時に行える。

if err := request.ParseForm(); err != nil {  
}  

こちらのほうがスコープが短くなるので良いらしい。

switch

switch variable {  
case 1:  
    return "one"  
case 2:  
    return "two"  
default:  
    return "other"  
}  

PHPと違って次のcaseには抜けない。次のcaseに抜けさせたい場合は fallthrough を使う。

タグなしswitchもある。

switch {  
    case num > 0:  
        return "正の数"  
    case num == 0:  
        return "ゼロ"  
    default:  
        return "負の数"  
}  

これは便利。PHPにもきてほしい。

ループ

とりあえず以下の2通り。whileなどない。

for i := 0; i < 10; i++ {  
}  

for index, value := range array {  
}  

引数

基本は値渡しではなく参照渡しになる。
ポインタを使うケースもあるが、使い分けはまだわかってない。

コマンドライン引数

args := os.Args()  

で取れる。

マップ

items = make(map[int]string)  

のように書ける。PHPのように何でも有りの連想配列ではなさそう。

ゴルーチン

非同期処理。

func main() {  
    ch := make(chan string)  
    go fetch("https://example.com", ch)  
    go fetch("https://example.org", ch)  
    fmt.Println(<-ch)  
    fmt.Println(<-ch)  
}  

func fetch(url string, ch chan<- string) {  
    res, err:= http.Get(url)  
    if err != nil {  
        ch <- fmt.Sprint(err)  
        return  
    }  
    ch <- res.Status  
}  

のように書く。
go でゴルーチンを作成し、それぞれのゴルーチンが非同期で動作する。
channel を使ってやり取りをする。いずれかのゴルーチンがチャンネルに対して受信・送信をするとそのゴルーチンは待機状態になり、他のゴルーチンが受信・送信することで処理が再開される。

無名関数

handler := func() {  
}  

名前付き型

type Point struct {  
    X, Y int  
}  

noshと私

たまには技術以外のことでも。

最近、 nosh を利用してます。

nosh.jp

僕は5月頃から使っていて、なんだかんだで既に90食くらい注文しているっぽい。
だいぶいい感じなので紹介したいと思います。

nosh is 何

簡単に言うと、「定期的におかずを届けてくれるサービス」。

Twitter とかで色んな漫画家がPRしてるので有名かも。

  • 定期的におかずが届く
  • おかずは主菜1品と副菜3品のセット
  • 主食(ごはん)は付いてない
    • パンはメニューとしてあるけどお値段高め
  • おかずは冷凍食品(なのでクール便で届く)
  • 届く間隔や個数は自由に設定できる
  • メニューは自分で選ぶこともできるし、おまかせにすることもできる
  • サブスクしかない
    • お試しで1回注文したい人は、サブスクに入って注文して即やめる感じになりそう?

自分はこうしてる

僕は6食/週で注文してます。
昼晩の食事を考えると週に14食なので、だいたい半分はnoshにしてる計算。
残りは学食を使ったり、外食したりしてます。

メニューは選ぶのが面倒なのでおまかせにしてます。
おまかせは結構偏りが多く、半分が鶏料理になってたりすることもあります。
僕は偏りがあってもあまり苦じゃないタイプなのですが、気にする人は自分でメニューを選択したほうがいいかも。

で、食事としてはだいたい以下のセットにして食べてます。

  • おかず: noshを解凍
  • ごはん: 事前に炊いて冷凍しといたのを解凍
  • 汁: インスタントのスープをつくる

特にスープを付けてからはだいぶいい感じになりました。
汁物大事。

nosh を使って良かったこと

食事を考える手間が省ける

自分的にはこれが一番大きいです。
「今日の晩ごはん何食べようかな」を考える手間が省け、冷凍庫の一番上に入ってるやつを食べるだけ。

特に忙しい時は、自分の世話のコストがなかなか馬鹿にならないし、かといって自分の世話をおろそかにすると巡り巡って効率が下がります。
食事について考えなくていいのは大事ですね。

普通に美味しい

不味くはない。美味しい。
ただ冷凍食品なので、基本的に水分多めです。
パリパリやサクサクとはご縁がないです。

痩せた

これは僕だけかもしれないですが、1食あたりの食事量がコンスタントになるので痩せました。
食事の量も、女性向けな感じの量で、男性的にはちょっと足りないぐらいかもしれません。

お腹は空くんですが、外に買い出しに行く気力も出ないので、結果的に痩せた感じですね。
無気力の勝利。

容器がかさばらない

1食ごとに別々の容器に入ってるのでゴミが増えそうな感覚はありますが、容器は重ねることができて、全然かさばりません。
僕は食べ終わったら軽くゆすいで、6食分の容器を重ねてまとめてポイしてます。

noshを使う際に気をつけたいこと

主食は自分で用意する必要がある

noshで届くのはおかずだけなので、ごはんやパンは自分で用意する必要があります。
noshでも一応パンのメニューはあるんですけど、1食あたりの金額を考えると割高です。

僕は週末に3合くらい一気にごはんを炊いて、冷凍してます。

冷凍庫を圧迫する

一人暮らし用の冷凍庫付き冷蔵庫を使ってる場合、6食入れるとパンパンです。
他の冷凍食品を入れておくスペースもないです。
なので、noshを使う際には冷凍食品はあらかじめ消費しといたほうがいいし、noshを使いはじめると冷凍食品は買えません。

洗い物は無くならない

noshだけで食事が完結しないので、基本的に洗い物は発生します。
でも調理器具を洗う必要がないのでラク。(炊飯器くらい)

安くはない

僕の場合、送料込みで6食で5000円くらいなので、1食800円くらい。
ここにごはん代とスープ代が加算されるので、外食と同じくらいのお値段はしてます。

1度の配達の量を増やせば少しはマシになるんでしょうが、そうすると冷凍庫のスペースが足らなくなるので、あまり現実的ではないです。
noshのために冷凍庫を別で買うのも微妙ですし、そもそも置くスペースがないです。

健康にいいのかはわからない

添加物とかどうなんだろう、気にしたことないからわからない。
でも、たとえ副菜が付いてても野菜の摂取量は圧倒的に足りないはず。

引きこもりが加速する

ただでさえリモートワークで引きこもり気味なのに、noshを使うとさらに引きこもりが加速します。
外食するためには外に出る必要があるし、自炊するためには食材を買うために外に出る必要があるんですが、noshにすると外に出る必要が全くありません。

まとめ

という感じで、良い部分もあれば気をつけたい部分もあるんですが、僕には結構フィットしていていい感じです。
たぶん普段から自炊してる人には向かないでしょうし、普段から外食や中食してる人には結構良いんじゃないかなと思います。

スクラム勉強会をやってみて

AIIT(大学院)のPBL(模擬プロジェクト)で「スクラムをやろう!でもスクラムがわからん!」ってなったのでスクラム勉強会をやりました。
メンバーの中では自分だけアジャイル開発の実務経験があったので、僕がファシリをさせてもらいました。

勉強会の概要

「SCRUM BOOT CAMP」をみんなで読むという形式にしました。

www.shoeisha.co.jp

「SCRUM BOOT CAMP」は自分はそこまで推していないのですが、まわりの評判はとても良かったので採用してみました。
あとは単純に、僕がスクラムの本をあまり知らなかったというのもあります。(「エッセンシャルスクラム」が個人的にはわかりやすくて好きなんですが、初心者が捌ける分量ではないので・・・)

勉強会の形式

自分が一番慣れているのは輪読会形式ですが、輪読会形式だと5,6回くらい続けないと読み終わらないので、時間の関係で不採用にしました。
あとは、新しいやり方にチャレンジしたいなと思ってたところもあります。

そこで今回は、全員で手分けをして本を読む「アクティブ・ブック・ダイアローグ」と、知識が偏らないようにする「Triple Nickels」を組み合わせる形式で行ってみました。
こんな感じです。

f:id:chiroruxx:20220326205456p:plain

結構諦めた部分もあります。
アクティブ・ブック・ダイアローグは共有後の議論が肝ですが、今回は議論をしていません。
Triple Nickelsも全員分まわすのが通常ですが、今回は2回のみです。
ここらへんは時間と人数の制約ですね。
時間をかけて深く理解するよりも、短時間で浅く全体を知ってもらいたかったので、今回は諦めました。

スクラム勉強会をスクラムっぽくやる

途中でこの形式はスクラム実践型だなと気付きました。
この形式で行うことで、スクラムの重要な要素を体験しながら勉強会に参加できます。

この形式では「読む・まとめる・発表する」を2回繰り返してます。
そう、繰り返してるんですよ。これはもはやスプリントですね!

そして繰り返しているので、2スプリント目では1スプリント目の結果を使うことができます。
1回目の「読む・まとめる」での手応えをもとに、2回目の「読む・まとめる」の時間配分をできますし、
1回目の「発表する」の感覚をもとに、2回目の「発表する」のシナリオを練ることができます。
まさに経験主義ですね!
時間配分については相対見積もりを使えそうな気もしますね!

「発表する」については、特にテンプレートなどは用意しないようにしました。
なので、「何を伝えたいか」「どのようにすれば伝わるか」は各自で考える必要があります。
スプリントレビューの準備で一番悩んだり時間かかるところと同じですね!

ちなみに、1人あたり40ページくらいを30分でまとめてもらいました。
この本は半分くらいマンガなので、実質20ページくらいですね。
それでも、30分で20ページをまとめるのはかなり厳しい話です。
この無茶振り・・・まるで開発現場のようですね?
アジャイルサムライで紹介されている3つの真実のうちのひとつ、「やるべきことはいつだって、与えられた時間と資金よりも多い1を思い出します。

そして2回目の発表では、1回目の発表資料を追記・編集するようにしてもらいました。
「自分で作り直したほうがラクなのになー」と思ってくれた参加者もいると思います。
あら、プロダクト開発でよく聞く悩みですね。
駆け出しエンジニアたちが見落としてそうなポイントだと思っているのですが、プロダクト開発では新規でコードを書くのではなく、既存のコードを修正したり追記したりすることがほとんどなんですよね。
今回はコードではなく発表資料ですが、同じことが体験できたのではないかなと思います。

進行するうえで気をつけたこと

ちょっといくつかは気をつけて進行を行いました。

タイムボックスを守る

アジャイル開発と切っても切り離せないのがタイムボックスだと思います。
特にスクラムは各イベントの時間も決まっているので、無視できません。
なのでタイムボックスについては強く意識をしてファシリテーションを行いました。

ただ、発表時に相手の発言を遮って止めるのは良くないかなと思ったので、区切りの良さそうな部分で「時間ですー」と入れるようにしました。

褒めない・指摘しない

今回に限らず、発表をきくと「よくわかってるな!」と思うことや「いやーこれは・・・」と思うことがよくあります。
勉強会のファシリとしては褒めたり指摘したりして方向付けをするのも手段のひとつではありますが、今回は行わないようにしました。
というのも、良かろうが悪かろうがその人が学んだということは事実で、それを尊重しようと思ったからです。
自分がフィードバックを返してしまうことで、学びの方向性が狭まってしまうリスクもありそうですしね。

ふりかえりを入れる

各発表のあとにふりかえりをする時間を設けてみました。
アジャイルと言えばふりかえり」というぐらいにふりかえりの重要性は大きいので、ふりかえりの雰囲気に慣れてもらうことが目的です。

あと、アジャイルだと意見を発散させる場面が多いので、発散の練習という意味もあります。
意見の発散は性格的な部分も多少は影響しますが、鍛えれば上達する技術です。

やってみて

自分でやってみた感想と、参加者からもらったフィードバックを参考にしつつ、ふりかえってみます。

わりと成功だったのでは

とりあえずみなさんには、「スクラム、思ったよりも簡単じゃなさそうだぞ」というのが伝わったように思います。
アジャイルをやったことない人はわりとミニウォーターフォールを想像される方が多いので、そうじゃないことが伝わっただけでも成功かなと思います。

要素を削ったほうがいいか?

参加者からのフィードバックの対象が人によってだいぶ違っていました。
とある人は発表について、とある人は時間について、別の人はドキュメンテーションについてと色々でした。

これは勉強会を設計する側の問題です。
要素を削ることによって、設計者が見てほしいところに参加者が向きやすくなるかなと思います。
ただ今回の場合は「広く浅く」がメインだったので、これでもいいのかなぁとも思います。

次に勉強会を設計する時には意識したいポイントです。

場を作る能力がほしい

個人的にはにこやかな雰囲気とか和気あいあいとした雰囲気が好きなんですけど、そういった場を作る能力はまだまだ足りないなーという感じです。

前に澤円さんの発表を聞いたときに、場を一気に和ませていたのを思い出しました。あんな風になりたい。

最近はリモート会議でもカメラオフにしているので、だいぶ表情筋が硬くなった気がします。
笑顔の練習でもしようかな?

余談

「SCRUM BOOT CAMP」の主人公はスクラムマスターで、チームの問題になりそうなことを事前に取り除いていくタイプでした。
僕はチームの前に転びやすそうな石を置いていくタイプのスクラムマスターです。
こういうのは性格が出ますね。


  1. オーム社, Jonathan Rasmusson アジャイルサムライ - 達人開発者への道