Go言語_2 - iosysRyoKoyasumi/learning GitHub Wiki

参考資料

Udemy視聴メモ

1. プロジェクト保存場所

Goのファイル管理について

Goのファイルは、従来は GOPATH/src 配下で管理することが一般的でした。
Go 1.13以降では、Go Modules機能が有効になったため、src フォルダが存在せず、binpkg のみの構成になるケースもあります。

ただし、個人開発では自分で src フォルダを作成し、その配下でプロジェクト管理を行う方法でも問題ありません。

GOPATHとは

GOPATH は、Goのワークスペースのパスを指定する環境変数です。
このディレクトリには、Goで作成したプロジェクトや、外部からインストールしたパッケージが保存されます。

GOPATHの役割

  • プロジェクトの保存場所
     ソースコードや依存するパッケージは、GOPATHで指定したディレクトリ内に保存されます。

  • ビルドとインストール
     go buildgo install などのコマンドを実行すると、GOPATH 内の適切なディレクトリに成果物が保存されます。

GOPATHのディレクトリ構造

  • src:ソースコードを保存する場所。プロジェクトや外部パッケージ等が格納されます。
  • pkg:ビルドされたパッケージファイルの保存場所。コンパイルされたライブラリが含まれます。
  • bin:ビルドされた実行可能ファイルが保存される場所。go install でインストールしたCLIツールなどがここに格納されます。

Go Modulesの導入

Go 1.11以降は、Go Modules が導入され、GOPATH を使用せずにプロジェクト管理が可能になりました。
Go Modulesを利用する場合は、プロジェクト内に go.mod ファイルを作成し、依存関係を明示的に定義できます。

2. 基本

変数

*** 暗黙的な変数の宣言の注意点

  • 暗黙的な変数の宣言で異なる型で再定義をすることはできない
  • 関数内でしか宣言できない
  • 基本的には明示的に型宣言をすることが推奨されている

基本型

数字型

int、floatはいくつか種類があるが、特別な理由がない限りはint、float64を使っておけば問題ない

uint、complex型

使用頻度は高くないので割愛

byte型

8ビットの符号なし整数を表す数。具体的には0~255

配列型

他言語と異なり、後から要素数の変更ができない。(要素数の変更ができるものは”スライス”)
Goの配列は性質が異なるので注意

インターフェース

全ての型と互換性のある特殊な型
初期値 = nil
演算に使用することはできない

型変換

キャストの方法は多言語と同じ
float64 → int にすると小数点以下切り捨て

i, _ := strconv.Atoi(s) // string → int

s := strconv.Itoa(i)    // int → string

ASCⅡとは

参考記事:https://e-words.jp/w/ASCII.html 英語で必要な文字を収録したコード規格

  • 7ビット (0~127)(または8ビット)で表される文字コード
  • 英数字(A~Z、a~z、0~9)や記号(+, -, *, /, @ など)、制御文字(改行、タブ など)を含む
  • 1970年代以降、コンピュータや通信の標準文字コードとして広く使われた

関数

宣言した変数を使用してない場合 変数宣言をした変数は必ず使用しなくてはいけない決まりがあるが、戻り値が二つある関数に対して片方の変数を「_(アンダーバー)」にすると、変数を使用せずともエラーが発生しなくなる

func Div (x, y int) (int, int) {
  q := x / y
  r := x % y
  return q, r
}

func main () {
  i, _ := Div(9, 3)
  fmt.Println(i) 
}
// Divの戻り値の一方を_にしているので使用しなくてもエラーが発生しない

クロージャー 関数の内部で定義された関数が、外部の変数を産しよう室図蹴ることができる仕組み

func Later() func(string) string {
	var store string
	return func(next string) string {
	// ここがクロージャー↓
		s := store
		store = next
		return s
	}
}

func main() {
	f := Later()
	fmt.Println(f("Hello"))
	fmt.Println(f("My"))
	fmt.Println(f("name"))
	fmt.Println(f("is"))
	fmt.Println(f("golang"))
}

// 出力結果
// 空の文字列
// "Hello"
// "My"
// "name"
// "is"

ジェネレーター 何らかのルールに従って呼び出すたびに新しい値を生成する関数のこと PHPやPythonにはメソッドとして備わっているが、GOではクロージャーを使用することで疑似的に再現できる

func integers() func() int {
	i := 0
	return func() int {
		i++
		return i
	}
}

func main() {
	ints := integers()
	fmt.Println(ints())
	fmt.Println(ints())
	fmt.Println(ints())
	fmt.Println(ints())
}
func integers() func() int {
	i := 0
	return func() int {
		i++
		return i
	}
}

func main() {
	ints := integers()
	fmt.Println(ints())
	fmt.Println(ints())
	fmt.Println(ints())
	fmt.Println(ints())
}

制御構文

型アサーション 新しい変数名 := 復元したい型 . (型)

var x interface{} = 3
i := x.(int)

switchを使用した型アサーション

var x interface{} = 3

switch x.(type){
case int:
  fmt.Println("int")
case string:
  fmt.Println("string")
default:
  fmt.Println("no")
}

ラベル付きfor

	Loop:
	for {
		for {
			for {
				fmt.Println("start")
				break Loop
			}
			fmt.Println("処理をしない")
		}
		fmt.Println("処理をしない")
	}
	fmt.Println("END")

“start“と”end”のみ出力されて途中の二行は出力されない defer deferで登録された処理は関数終了時に実行される

func TestDefer() {
	defer fmt.Println("end")
	fmt.Println("start")
}

func main() {
  TestDefer()
}

// 出力結果
// start (関数終了)
// end   (終了後、処理が実行)

deferが複数登録された場合、最後に登録された処理が最初に実行される panic プログラムの実行を途中で止めるためのもの recover panicをキャッチしてプログラムのクラッシュを防ぐための仕組み deferの中でしか使えない 並行処理 go 関数()

func sub() {
	for {
		fmt.Println("sub loop")
		time.Sleep(100* time.Millisecond)
	}
}

func main() {
  	go sub()

	for {
		fmt.Println("main loop")
		time.Sleep(200*time.Millisecond)
	}
}

// 出力結果
// sub loop
// main loop
// sub loop
// main loop
// 以下無限に継続

init関数

  • 自動で実行される
  • 引数なし / 戻り値無し
  • main関数より先に呼ばれる
  • 各パッケージで複数作れる

設定の読み込み、データの初期化等で利用される。

参照型

スライス 配列とは異なり、可変長な参照型

	var sl2 []int = []int{100, 200}
	fmt.Println(sl2)

	sl3 := []string{"A", "B"}
	fmt.Println(sl3)