GO言語(golang)1.20をはじめる③/最低限の文法をまとめる
目次
GO言語(golang)1.20をはじめる③/最低限の文法をまとめる
前2回で、開発環境構築と「パッケージ」「モジュール」の意味を整理しました。
あとは、 最低限の文法を整理すれば、とりあえずプログラムは作れます。
文法:パッケージとimport
Goのプログラムは main パッケージから開始されます。
package main
importは{}でくくって宣言するのが推奨です。
import (
"fmt"
"math"
)
文法:関数
関数は「func」で宣言します。
main()がまず実行されます。
func main() {
fmt.Println(add(42, 13))
}
関数の引数は必ず型を宣言する必要があります。
戻り値の型も宣言が必要です。
戻り値の型(例だとint)は後ろに置きます。
func add(x int, y int) int {
return x + y
}
関数の戻り値を複数定義する場合は、以下のようになります。
func swap(x, y string) (string, string) {
return y, x
}
文法:組み込み型
基本の組み込み型です。
bool
string
int int8 int16 int32 int64
uint uint8 uint16 uint32 uint64 uintptrbyte // uint8 の別名
rune // int32 の別名
float32 float64
complex64 complex128
NULLにあたるものは
です。
文法:キャスト(型変換)
Go言語での型変換は明示的な変換が必要です。
例えば、上記の「int」型を「float64」型に変換(キャスト)するには。
var i int = 42
var f float64 = float64(i)
みたいにします。
文法:変数
変数は「var」で宣言します。
外部パッケージから参照可能(public)な変数は「大文字」、パッケージ内だけしか参照できない(private)変数は「小文字」で始めます。
型は後ろに置きます。
var i int
var f float64
型を明示的に指定しないと、右側の変数から型推論(Type inference)します。
i := 40 // intに型推論される
これを使って複数の変数をいっぺんに初期化することもできます。
var i, j int = 1, 2
変数を初期値を与えずに宣言すると以下のゼロ値が設定されます。
- 数値型(int,floatなど): 0
- bool型: false
- string型: "" (空文字列( empty string ))
関数の中で、varを使わずに「:=」で暗黙的な宣言もできます。
関数内で使い捨てのカウンタみたいなものなら、これだけでもOKです。
k := 3
前に説明した型変換も、これを使って、以下のように書けます。
i := 42
f := float64(i)
文法:定数
定数はconstで宣言します。
const Pi = 3.14
定数で宣言できるのは
- 文字(character)
- 文字列(string)
- boolean
- 数値(numeric)
のみです。
定数は := を使って宣言することはできません。
文法:演算子
一覧にまとめてくれているページがあったので、リンクだけ載せておきます。
基本的な部分は他の言語とほぼ同じです。
文法:固定長配列
固定長配列(Arrays)はサイズを指定し、型を後ろにおいて宣言します。
var a [2]string
a[0] = "Hello"
a[1] = "World"
配列は上記のように固定長のものを指します。
以下のような初期化の仕方も可能です。
arr := [...] string{"Hello", "World"}
文法:可変長配列(スライス)
サイズを指定しないで宣言するのが「スライス(Slices)」です。
var s int
何もはいっていないときは「 nil」 です。
定義後の要素の追加は、append()で行います
追加後の戻り値は「新しいスライス」になります。
new_slice = append(s, 0)
宣言時の初期化も可能です。
new_slice := int{2, 3, 5, 7, 11, 13}
pythonのスライスっぽい参照の仕方ができます
new_slice = s[1:4]
スライスの指定の仕方の簡単な例です。
- s[start:end] → start から end - 1 まで
- s[start:] → start から最後尾まで
- s[:end] → 先頭から end - 1 まで
- s[:] → 先頭から最後尾まで
長さの確認は「len」を使います。
len(s)
文法:連想配列(map)
mapの初期化の方法は「make」を使う方法と、使わない方法があります。
makeを使う方法です。
m := make(map[string]string)
m["first"] = "Mike" //マップにkeyとvalueを挿入する。
m["second"] = "Smith"
同じことをmakeを使わないでやるとこうなります。
var m = map[string]string{"first":"Mike", "second": "Smith"}
mapへの追加・要素の取得・削除の仕方です。
m[key] = elem
elem = m[key]
delete(m, key)
mapの要素の存在確認はちょっと変わっていて、例えば、keyが存在するかどうかは、以下のように要素の取得時に2番目に変数「ok」等を書きます。
elem, ok = m[key]
存在すればokがtrue、しなければfalseになり、okの場合はelemに値がセットされます。
文法:ループ (カウンタ利用)
forループはC言語っぽいですが、「i := 0; i < 10; i++」の部分を()で囲みません。
for i := 0; i < 10; i++ {
sum += i
}
ループを途中で打ち切るには「break」。
スキップして次にうつるには「continue」です。
文法:ループ(スライス)
スライスやmapの場合は、rangeで取り出しながらループします。
スライスの場合は、index、valueが取得できるので、以下のようになります。
var pow = int{1, 2, 4, 8, 16, 32, 64, 128}
for index, value := range pow {
fmt.Printf("index(%d) : value(%d)\n", index, value)
}
文法:ループ(map)
mapの場合は、key、valueを取り出します。
var m = map[string]int{ "one": 1, "two": 2}
キーのみが欲しい場合は「key,_」、valueのみなら「_,value」のように「_」で不要な部分を指定することもできます。
文法:条件分岐(IF)
if文も同様に「 x < 0」の部分を()で囲みません。
if x < 0 {
return sqrt(-x)
}else{return 0
}
文法:条件分岐(switch)
switch~case文はbreakを書かなくても、GOが自動的に補完してくれます。
t := time.Now()
switch {
case t.Hour() < 12:
fmt.Println("Good morning!")
case t.Hour() < 17:
fmt.Println("Good afternoon.")
default:
fmt.Println("Good evening.")
}
文法:ポインタ
GO言語はポインタが使えます。
C言語っぽいですが、C言語と違ってポインタ演算はできません。
var p *int
i := 42
p = &i
文法:defer
defer に渡された関数は、呼び出し元の関数の終わり(returnする)まで実行されません。
簡単な例で書くと。
func main() {
defer fmt.Println("world")fmt.Println("hello")
}
のように書かれたものを実行すると「fmt.Println("hello")」が先に実行されて、deferに渡された「fmt.Println("world")」はmain()関数の終わりに実行されます。
なので。
hello
world
と結果が表示されます。
これはエラー処理などで、とても役にたちます。
defer へ渡した関数が複数ある場合スタック( stack )されて「 LIFO(last-in-first-out) 」の順番で実行されます。
文法:構造体
struct(構造体)は以下のように定義します。
type Vertex struct {
X int
Y int
}
構造体の初期化はをつかっておこない、メンバには、ドット(.)でアクセスできます。
v := Vertex{1, 2}
v.X = 4
GO言語にはクラスはありません。
ですが、型にメソッドを定義するなどして、クラスっぽいことを実現する方法はあるみたいです・・ただ、そのへんに踏み込むと「最低限」ではなくなるので、そこは別の機会にまとめることにします。
文法:コメント
// と /* */が使えます。
//以降の文字列をコメントとします。
こちらは1行コメントです。
/* */で囲まれた部分をコメントとします。
/* */では複数行のコメントを書くことができます。
まとめ:簡単なコードを書いて試してみる
動作確認用に簡単なコードを書いてみました。
package main import ( "fmt" "time" ) func main() { var mapd = make(map[string]string) var now = time.Now() var layout = "2006/01/02" mapd["今日"] = now.Format(layout) var tomorrow = now.AddDate(0, 0, 1) mapd["明日"] = tomorrow.Format(layout) var nextmonth = now.AddDate(0, 1, 0) mapd["一月後"] = nextmonth.Format(layout) for key, value := range mapd { if key != "今日" { fmt.Printf("%sは%sです\n", key, value) } else { fmt.Printf("%sは%sです\n", value, key) } } switch { case now.Hour() < 12: fmt.Println("Good morning!") case now.Hour() < 17: fmt.Println("Good afternoon.") default: fmt.Println("Good evening.") } new_slice := []int{2, 3, 5, 7, 11, 13} fmt.Println(new_slice[2:4]) }
実行タイミングによって変わりますけど、こんな結果が表示されます。
2023/06/03は今日です
明日は2023/06/04です
一月後は2023/07/03です
Good evening.
[5 7]
いけてますね。
最低限の文法としては、こんなもんかと思います。
ではでは。