0
0

More than 1 year has passed since last update.

【Golang】 基礎

Posted at

変数の省略定義

// 型は自動で推測される
name := "John"

// 以下と同じ
var name string
name = "John"

名前付き戻り値

戻り値を変数として定義しておくことで、return のみで返却できる

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

func main() {
	a, b := swap(10, 7)
	fmt.Println(a, b)
}

Defer

defer へ渡した関数の実行を、呼び出し元の関数の終わり(returnする)まで遅延させる。
defer へ渡した関数が複数ある場合、その呼び出しはスタック( stack )されます。 呼び出し元の関数がreturnするとき、 defer へ渡した関数は LIFO(last-in-first-out) の順番で実行されます。

func main() {
	defer fmt.Println("world")
	fmt.Println("hello")
}
// 結果
// hello
// world

func main() {
	fmt.Println("counting")
	for i := 0; i < 10; i++ {
		defer fmt.Println(i)
	}
	fmt.Println("done")
}
// 結果
// counting
// done
// 9```
// 8
// .
// .
// 0

スライス

スライスは配列への参照のようなものです。
スライスはどんなデータも格納しておらず、単に元の配列の部分列を指し示しています。
スライスの要素を変更すると、その元となる配列の対応する要素が変更されます。
同じ元となる配列を共有している他のスライスは、それらの変更が反映されます。

func main() {
	names := [4]string{
		"John",
		"Paul",
		"George",
		"Ringo",
	}
	fmt.Println(names)

	a := names[0:2]
	b := names[1:3]
	fmt.Println(a, b)

	b[0] = "XXX"
	fmt.Println(a, b)
	fmt.Println(names)
}

// 結果
// [John Paul George Ringo]
// [John Paul] [Paul George]
// [John XXX] [XXX George]
// [John XXX George Ringo]

注意点
配列 (スライス) を部分的に参照する際、終了インデックスに指定する値は [実際のインデックス+1]
イメージ

s = []int{10, 20, 30, 40, 50, 60}
// start_index >= 2 ~ end_index < 4 までの要素
s1 := s[1:4]  //=> [20, ]

Make関数

// Make関数
// 第1引数:スライスの型
// 第2引数:スライスの長さ
// 第3引数:スライスの容量

// 長さ5 要素int型のスライス作成
a := make([]int, 5)
==> [0, 0, 0, 0, 0] //結果 要素は全てゼロ値(int型の場合は0)で初期化される

// 長さ0 容量5 要素int型のスライス作成
// 将来的に最大で5つの要素を格納できる
b := make([]int, 0, 5)
==> [] //長さ0なので要素なし

ループ

スライスをrangeで繰り返す場合、rangeは反復毎に2つの変数を返します。 1つ目の変数はインデックス( index )で、2つ目はインデックスの場所の要素のコピーです。

func main() {
	for i, v := range pow {
		fmt.Printf("2**%d = %d\n", i, v)
	}
}

Map

// key:int value:文字列 とするマップを作成
e := make(map[int]string)
e[1] = "1st"  // 追加
e[2] = "2nd"
e[3] = "3rd"
fmt.Println(e)
delete(e, 2)  // 削除
fmt.Println(e)

// 存在確認
elem, ok := e[1]
fmt.Println("The value:", elem, "Present?", ok)

// 結果
// map[1:1st 2:2nd 3:3rd]
// map[1:1st 3:3rd]
// The value:  Present? false

クロージャ

クロージャは、外部のスコープにある変数を参照し、その変数を保持して利用する関数です。Golangでは、無名関数(関数リテラル)を使ってクロージャを作成します。無名関数は func() ... という形式で表現され、その関数型の戻り値として返すことでクロージャとして機能します。

package main
import "fmt"

// クロージャを返す関数
func counter() func() int {
    count := 0
    return func() int {
        count++
        return count
    }
}

// count変数の値を取得する関数
func getCount() int {
    return counter()()
}

func main() {
    increment := counter()

    fmt.Println(increment()) // クロージャを呼び出して countの値を更新。1が出力される
    fmt.Println(increment()) // クロージャを呼び出して、countの値を更新。2が出力される

    fmt.Println(getCount())  // countの現在の値を取得する(クロージャの再生成はしない)2が出力される
}

このコードでは、counter()関数がクロージャを返しています。counter()関数内部でcount変数が定義されており、この変数はクロージャに含まれています。クロージャはcount変数にアクセスして、その値を更新しています。

increment変数はcounter()関数を呼び出してその結果として返されるクロージャを保持しています。このクロージャを呼び出すたびに、count変数が更新され、新しい値が返されます。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0