Go言語の特徴
Go言語の特徴についてまとめてみました。これからGoを学習しようとしているひとはぜひ参考にしてみてください。
表示系
改行なし表示
・Print()
改行あり表示
・Println()
ファイルアウトプットをする
・Fprint()、Fprintf()、Fprintln()
はじめにFのついているものは、書き込み先を明示的に指定します。ファイルというのは、物理的なファイルではなく、標準出力等のファイルポインタで示される箇所に出力をするという意味です
fmt.Fprint(os.Stdout,"Hello world!")
文字の型について
Go言語には1文字の型(C言語でいう文字型)はなく、すべて文字列として扱います。しかしながら、C言語との整合性をとる必要のある場合、1文字の型はC言語と同様にint型で受けることが可能です。
Go言語だけで1文字を扱う場合は、すべてルーン文字(rune=int32型)として扱う必要があります。Byte型で受けるとエラーになりやすいです。
たとえば%Tという変換指定子がGo言語にはありますが、これは、その変数の型を表示します
文字コード
Go言語はUTF-8しか受け付けません
変数宣言
関数内に限り、
「:=」
のように宣言することで、動的型付けが可能
マップ(map)
マップは、スクリプト系言語ではおなじみの連想配列です。
Switch文
Go言語ではcase節内のbreak文は不要です。
下のcase節に処理を落としていきたいときには、
fallthrough文を付けましょう。
case節に条件判定文を置くことが可能です。
くりかえし(ループ処理)
Go言語には、for文しかありません。
foreach文もありません。これはrangeで代用できます。 (for-rangeループ)
※for-rangeループの注意点として、取り出される値の順序が保証されていないということです。
forの処理の中の変数は一種のローカル変数でforブロックの中でのみ有効です
関数型の変数
関数型の変数は、専用の関数型として通常の変数のようにあつかうことができます。内部でやってることは、関数へのポインタです。
Go言語の関数は第一級オブジェクトなので、変数への代入、引数への代入も可能であり、戻り値にすることも可能です。
このようにして、オブジェクト指向の体裁がなくてもオブジェクト指向と同様のことが表現できます。
クロージャー
関数のローカル変数を参照している、関数内関数のことです。
package main
import "fmt"
func main() {
var kansu = fn()
fmt.Println(kansu()) // 1
fmt.Println(kansu()) // 2
fmt.Println(kansu()) // 3
}
func fn() func() int {
x := 0
return func() int {
x++
return x
}
}
このように、関数内のローカル変数を定数のように扱うことができます。変数を内部に閉じてしまう(Closeする)ので、Closureといいます。
defer 実行終了時の遅延実行
呼び出した関数が終了するときに、実行したい処理を遅延実行する文です
package main
import "fmt"
func main(){
yobidasi()
}
func yobidasi(){
defer fmt.Println("終了")
fmt.Println("先に表示")
}
パニックSTOP
C言語では、プログラムから復帰する関数にexit()がありました。Go言語にもOSパッケージにExit()があります
パニック関数は
致命的なエラーになるような場合にその前に、プログラムを終了するためにある関数です。
ただし、panicが呼び出されると、スタックフレームを記録して、メインに戻り、スタックフレームを表示してからプログラムを終了するところが、exit()関数とことなります。
スタックフレームについてはこちらが詳しく書いてあります。関数を呼び出す際に、スタックというデータ構造のメモリに積まれるデータをまとめたものです。
C言語関数辞典 - C言語用語集 スタックフレーム (stack frame)
オブジェクト指向的なGo言語
Go言語はオブジェクト指向言語ではありませんが、オブジェクト指向のよい部分を取り込んでいるため、C言語にはない特徴があります。それが、メソッドとインターフェースです。
Go言語は型として、インターフェース型をもっています。
インターフェース型は、メソッドの関数宣言のみを記述し、必要に応じてその関数の中身をその型のメソッドとして実装します。
これはシステム設計上の利点となります。なぜなら、関数の宣言部さえあれば、その関数が実装されているものとして他の部分のコードを完成させることが可能だからです。
オブジェクト指向では、親クラスと継承したクラスがそれをになっています。親クラスのメソッドを、インターフェースで宣言しておき、親クラスから継承したクラスとして、使用することがおおいです。
しかし、親クラスに変更があった場合、変更対応がむずかしくなることがあります。この場合、delegate(移譲)することで、対応するのがGo言語なら可能です。
Go言語の場合、インターフェースと構造体を組み合わせることで、メソッドを構築することができる。
並列処理が記述可能(Goroutine)
Goルーチンを使用することで、複数のサブルーチンを同時に実行できます。つまり、Go言語は並列処理を標準で記述できる言語なのです。
GNUコンパイラが並列処理のしくみの根本となっています。
並列処理の記述にはきまりがあります。グローバル変数をGoルーチンのなかで使用することは避けるべきだとされています。同時にその変数が使用される可能性があるということは、何が起こるかわからなくなるからです。そのため、排他処理の記述をする必要があります。
(どうしてもグローバル変数の参照をしなくてはならない場合には、セマフォやミューテックスを利用して、排他処理、順番待ち処理をする必要が出てきます。
しかしながら、Go言語がマルチタスクを実行するときに使用することが許されているスレッドはひとつだけなので、あまり複数の処理を並列化して実行すると、処理が正常におこなわれることが保証されません。
そのような場合には、C言語の方で並列処理を記述して、それをGo言語から呼び出すというCGOのプログラムを組んだほうが確実です。
なお、Go言語を本腰を入れて学びたいひとは、Udemyなどによいレッスンがあったりします。ぜひUdemyでGoと検索してみてください。
ではでは!