bam6o0の記憶域

忘備録になればいいな

Go言語の勉強記録15bit

インターフェイス

  • インターフェイスは振る舞いを規定する。
  • 中身を持たない関数のようなもの
  • ロジックは持たず、ロジックは別で記述される。
  • ロジック部分はインターファイスの実装と呼ぶ。
  • インターファイスは関数の名前・パラメータ・戻り値だけを定義したもの。
  • インターファイスが実装するのは型
  • インターファイスで定義されえいる関数をメソッドとして実装すれば、自動的にインターファイスを実装したことになる。
  • インターファイス型の変数にはインターファイスを実装している型のポインタを代入可能
  • 書式
interface {
  関数名(パラメータリスト)戻り値の型
  関数名(パラメータリスト)戻り値の型
  :
}

//インターファイス型として宣言する
type インターファイス型名 interface{
  関数名(パラメータリスト)戻り値の型
  関数名(パラメータリスト)戻り値の型
  :
}

実行結果

$go run interface.go
和: 3
差: -1

Go言語の勉強記録14bit

構造体

  • フィールドと呼ばれる要素の集合体
  • 各フィールドはそれぞれ名前と型を持つ
  • データの構造を定義する時に使う。
  • フィールドにアクセスするときはフィールドを持つ値の後ろに.を記述し、その後ろにフィールド名を記述する。
  • 先頭一文字を大文字にするとエクスポート

構造体型の書式

  • 書式
struct {
  //フィールドの宣言
} 

実行結果

$go run struct.go
{1 2 3.14 go}

構造体に名前をつける

  • typeキーワードを使用して名前を付ける。
type MyDate struct{
  s string
  b byte
}

ブランクフィールド

  • フィールド名にブランク識別子を使用できる。
  • ブランクフィールドと呼ばれる
  • メモリ領域として確保は必要だが、実際にそのフィールドにアクセスすることはないということを明示的に表すために使用
  • パディングなど
  • 構造体内に同一の名前を持つフィールドは宣言できないが、ブランクフィールドは複数宣言可能
  • 書式
struct {
  b1 byte
  _  byte
  b2 [5]byte
  _  byte
}

匿名フィールと埋め込み

  • フィールドの宣言が型だけ、フィールド名を省略した時匿名フィールドとなる。
  • 型の名前がそのフィールド名となる
  • 書式
struct {
  int
  uint64
  *byte
}
  • 匿名フィールドが持つフィールドとメソッドが、埋め込み先の構造体型にも実装されているかのように扱われるから。
  • 継承ににてる

実行結果

$go run embed.go
test.doSomething()
0

構造体の初期化

  • 構造体リテラルを使うと宣言と同時に変数を初期化できる。

実行結果

$go run struct_init.go
{Jhon 23} {Tom 32} {Jane 42} &{Mike 36}

Go言語の勉強記録13bit

関数の遅延実行

  • 関数の実行を遅延させる時はdefer文を使う。
  • 通常はコードは記述された箇所で実行される。
  • 呼び出された関数の処理が完了してから、それ以降のコードが実行される。
  • 関数呼び出しを遅延指定した場合、その時点で実行されずdeferを呼び出した呼び出し元の関数から抜けた時に実行
  • 書式
defer 関数呼び出し
  • 遅延した関数から戻り値は受け取れない
  • deferを複数回使用した時はそれぞれの関数が指定した順に実行

実行結果

$go run defer.go
開始
終了
delayが呼び出されました

遅延実行の有用性

  • リソースの解放に便利
  • ファイルのクローズといったリソースの解放処理に使用すると便利

実行結果

$go run  defer_close.go
$cat test.txt
あいうえお

Go言語の勉強記録12bit

メソッド

  • 型にメソッドをもたせることが出来る。
  • メソッドも関数の一種
  • 特定の型と結びつけることが出来る。

メソッドの宣言

  • 書式
func (レシーバの変数名 レシーバの型) メソッド名(パラメータリスト) 戻り値の型{
  //処理
  
  //呼び出し元への復帰
  return 戻り値
}
  • レシーバが追加
  • レシーバによってメソッドがどの型に所属するか決まる。
  • レシーバの変数名と型を()内に記述
  • 呼び出すときはメソッドの持つ値の後ろに.を記述し、メソッド名を記述する。
  • レシーバの変数名は省略可能
  • 省略した場合、変数名を使ってメソッド呼び出しの対象となった値へアクセスができない。
  • レシーバとして使用する型は、メソッドと同じパッケージ内で宣言されている必要がある。
  • インターフェイス型はレシーバにできない。

実行結果

$go run method.go
1234

レシーバをポインタにする

  • レシーバ変数を使ってメソッドを呼び出した対象の値にアクセスできる
  • 値をメソッド内で変更するにはレシーバの型をポインタにする
  • はじめからポインタである型は使用できない

実行結果

$go run receiver_ptr.go
0
2

メソッド値

  • 値とメソッドの紐付けをメソッド値として扱える。
  • メソッド値は関数のように呼び出せる。
  • 通常は紐付けられている値のメソッドが暗黙的に呼び出される。

実行結果

$go run method_value.go
3
6

Go言語の勉強記録11bit

関数

  • 特徴は戻り値として複数の値を返せる。

関数の宣言

  • 書式
func 関数名(パラメータリスト) 戻り値の型{
  //処理

  //呼び出し元への復帰
  return 戻り値
}
  • パラメータリストには変数名と型の順に,で区切って列挙
  • 戻り値なければ省略可能

実行結果

$go run function.go
3
  • cに慣れているとパラメータリスト後の戻り値の型を忘れがち
  • main関数はパラメータおよび戻り値を持たない決まり。

多値を返す関数の宣言

  • 戻り値の型のリストを()で囲む
  • 書式
func 関数名(パラメータリスト) (戻り値の型リスト){
  //処理
}

実行結果

$go run multi.go
3 -1 2 0.5

関数から返された多値を直接他の関数に渡す。

  • 関数から返された戻り値の数と型が他の関数のパラメータの数と型と一致しているとき、戻り値を関数のパラメータとして直接渡せる。
  • 戻り値とパラメータの数が完全に一致している必要はない。
  • 型は戻り値の型がパラメータの型へ代入可能であれば完全に一致している必要はない。

実行結果

$go run multi_param.go
0 xyz 3.14

可変長パラメータ

  • 関数の最終パラメータは可変長パラメータとして利用可能
  • 可変長パラメータは関数を呼び出す側で、そのパラメータに渡す値の数を自由に決められる。
  • 関数宣言のパラメータの型の前に...を記述する。
  • 可変長パラメータを受け取る関するでは、この可変長パラメータの値をスライスとして受けとる。

実行結果

$go run variadic.go
1月の祝日は2日あります。
元旦
成人の日
2月の祝日は1日あります。
建国記念日
3月の祝日は1日あります。
春分の日

戻り値に名前を付ける

  • Goは戻り値に名前を付けられる。
  • 呼び出し元に返したい値をその変数に代入し、retrun文をパラメータなしで実行すると、retrun文にパラメータを与えたのと同じように戻り値を返せる。
  • 名前付き戻り値の初期値はゼロ値

実行結果

$go run return.go
3 -1 -1 0.5

関数リテラル

  • 名前を持たない関数、匿名関数
  • 関数内で記述する
  • 関数リテラルは関数リテラルの外側で宣言された変数にアクセス可能
  • 一般的にクロージャと呼ぶ
  • 名前がないため記述と呼び出しを同時に行うか、変数に代入して呼び出す
  • 書式
func(パラメータリスト)戻り値の型{
  //処理
  //呼び出し元への復帰
  return 戻り値
}

実行結果

$go run function_literal.go
1230

関数型

  • 関数を変数に格納する時、関数型を使用する。
  • その変数を使って格納されている関数を呼び出せる。
  • 初期化されていない関数型の初期値はnil
  • 書式
func (パラメータリスト)
func (パラメータリスト) 戻り値の型
func (パラメータリスト) (戻り値の型リスト)

実行結果

$go run function_type.go
3
2

init関数

  • 宣言しておくとmain関数より前に自動的に呼び出される
  • 初期設定処理を記述する。
  • パラメータも戻り値も持たない。
  • 1つのソースファイル内で複数のinit関数を記述できる。

実行結果

 $go run init.go
初期設定処理
main関数

Go言語の勉強記録10bit

ラベル

  • break文、contineu文、goto文の宛先となる識別子
  • 宣言だけして使用しないとエラー
  • ラベルを宣言した関数内でのみ有効
  • 書式
ラベル名:

ラベルにbreakする

  • break文は通常は最も内側にあるfor文、switch文、select文の実行を中断する。
  • ラベルを使用するとネストした中で任意のfor文、switch文、select文の実行を中断できる。

実行結果

$go run label_break.go
0
1
2

ラベルにcontinueする。

  • for文内のcontinueも、任意のfor文の実行を中断させることができる。

実行結果

$go run label_continue.go
0
  0
  1
  2
1
  0
  1
2
  0
  1
  2

goto文

  • 指定したラベルを付けた分にプログラムの実行を移動する
  • 使用に制限あり
  • goto文の実行に酔ってそれまでスコープ外だった変数がスコープ内に入ってしまう場合はエラー
  • 書式
goto ラベル

実行結果

$go run goto.go
add 1
add 3
add 5
add 7
add 9

Go言語の勉強記録9bit

ポインタ

  • 変数が存在するメモリ上の場所をアドレスという。
  • そのアドレスを格納可能な変数をポインタをいう。
  • int型変数のアドレスを格納できるポインタの型は*intと記述し型の前に*を付ける。
  • 変数からアドレスを取得する時は&(アドレス演算子)を使う。
  • アドレスか指し示す変数にアクセスするときは*を使う。

実行結果

$go run pointer.go
iのアドレス 0xc42006e178
ptrの値(変数iのアドレス: 0xc42006e178
iの値: 12345
ポインタ経由のiの値 12345
ポインタ経由で変更したiの値: 999

ポインタ渡しと値渡し

  • ある変数を関数に渡すと、実際の値はコピーされる。
  • コピーされた値を関数内で変更しても関数の呼び出し元の値には影響がない。
  • 値のポインタを関数に渡した時は、値の実態は関数の呼び出し元と同じ。
  • ポインタを渡した場合は関数内で呼び出し元の値を変更できる。
  • ポインタをつかって値を受け渡すことをポインタ渡しという。
  • 値のコピーを受け渡すことを値渡しという。
  • GoではCとは違い、ポインタの値を演算できない。

実行結果

$go run pointer_value.go
値渡し: 1
ポインタ渡し: 2

new組込み関数によるメモリの割り当て

  • アドレスは変数を間接参照したときだけではなく、明示的に新しいメモリを割り当てることでも得られる。
  • メモリを割り当てるにはnew組込み関数を使用する。
  • メモリを割り当てたい型を指定する。
  • new組み込み関数を死闘して割り当てられたメモリはゼロ値で初期化される。
  • 割り当てたメモリが使わなくなったと判断されると自動的に解放される。
  • 書式
new 型
  • 使用例
var i *int new(int)

var s *string = new(string)

ゼロ値

  • 変数を明示的に初期化しなかった時に暗黙的に設定される初期値
  • 変数の型によってゼロ値はことなる。
  • 論理値型 false
  • 数値型 0
  • 文字列型 ""
  • 配列型 各要素がゼロ値の配列
  • 構造体型 各フィールドがゼロ値の構造体
  • その他 nil

nil

  • nilとは値がない状態
  • CでのNULL
  • Javaでのnull
  • nilは比較演算子で比較できる。
if s == nil{
  fmt.Pritnln("nilです")
}

if s != nil{
  fmt.Println("nilではない")
}