Goに入門したので期間中の学びを垂れ流す

Published
2023-06-12
Author
びきニキ
Tags

ハックツハッカソン~メガマウスカップ~に参加しました。 普段はフロント園児なのですが、まさかのバックエンド担当になりGoを書くことになったので、期間中に勉強した内容をここに垂れ流します。


Goとは

  • Googleが開発したプログラミング言語(Google内の課題を解決するために開発されたそう)
  • 強力でシンプルな言語設計、複数のプログラムを同時に実行する”並行プログラミング”が特徴


変数

ゼロ値があり、初期化しなくても利用できる

  • 数値型(int, float64など)は「0」
  • 文字型(string)は「””」
  • boolは「false」
  • errorは「nil」


定数

型を明示しない場合、定数はデフォルトの型を持つ

  • 整数(100)はint
  • 浮動小数点(1.5)はfloat64
  • 複素数(1+4i)はcomplex128
  • ルーン(’A’,’朝’)はrune
  • 文字列(”niki”)はstring
  • 真偽値(ture)はbool


代入演算


Goの特徴

  • Goはコンパイル時の後ろの改行を見て、自動でセミコロンを付与している
// OK
if a == 0{
}

// NG
if a == 0 // 0の後に;を付与するので、謎の{}が残る
{
}


  • 繰り返しはforしか存在しない(=if文がない)
// 初期値; 継続条件; 更新文
	for i:=0; i<=100; i=i+1{
}

// 継続条件のみ(while的な役割)
for i<=100 {
}

// 無限ループ
for {
}

// rangeを使った繰り返し
for i, v:=range[] int{1,2,3}{
}


テスト書くとき

  • xxx_test.goのような名前のファイルにする
  • テスト関数はTestという単語で始める
  • テスト関数は1つの引数のみをとる。 t *testing.T
  • *testing.T 型を使うには、他のファイルの fmt と同じように import "testing" が必要
  • * testing.Tタイプのtがテストフレームワークへのhook


🐇 usage

// hello.go
package main

import "fmt" // Println関数を含むパッケージをインポート

// Hello関数を定義
func Hello() string {
    return "Hello, world"
}

// main関数を定義
func main() {
    fmt.Println(Hello())
}
// hello_test.go
package main

import "testing"

func TestHello(t *testing.T) {
		got := Hello()
		want := "Hello world"

		if got != want {
				t.Errorf("got %q want %q", got, want)
		}
}
go test
PASS
ok      hello/src       0.002s

// 失敗するとこんな感じ
go test
--- FAIL: TestHello (0.00s)
hello_test.go:10: got "Hello, world" want "Hello! world"
FAIL
exit status 1
FAIL    hello/src       0.005s

naked return

戻り値に名前をつけると、return ステートメントに何も書かずに戻すことができる

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

func main() {
	fmt.Println(split(17))
}
  • naked returnステートメントは、短い関数でのみ利用すべき
  • 長い関数で使うと読みやすさに悪影響がある


Defer

 defer へ渡した関数の実行を、呼び出し元の関数の終わり(returnする)まで遅延させるもの。

package main

import "fmt"

func main() {
	defer fmt.Println("world")

	fmt.Println("hello")
}

// hello
// world と返ってくる 

defer へ渡した関数が複数ある場合、その呼び出しはスタックされる。スタック後は、後ろから取り出される(LIFO(last-in-first-out)

雑多メモ

  • 型を後ろに書く(気持ち悪い)→ 日本語みたいな感じだと思えば許せるし、人間的には左から右へ文章を読むのでやさしい
  • 2つ以上の引数が同じ型である場合には、最後の型を残して省略できる → うれしい


package main

import "fmt"

// 関数名(入力値とその型)(戻り値の型)
func swap(x, y string) (string, string) {
	return y, x
}

func main() {
	a, b := swap("hello", "world")
	fmt.Println(a, b)
}