Open2
Go学習メモ(知見がまとまったら記事化します)
Goで変数名の後ろに型名を書く理由
(https://go.dev/blog/declaration-syntax)
C言語
C言語では型(type)が左,式(expression)が右
int x;
int main(int argc, char *argv[]) { /* ... */ }
C言語流の記法は型が少ないうちはいいが,型が複雑になってくると難読化する
//int型引数を2つ取る関数型ポインタ
int (*fp)(int a, int b);
//fpの引数にint (*fp)(a, b) を渡す場合...
int (*fp)(int (*ff)(int x, int y), int b). //???
//関数ポインタを返す場合(もはや何が帰ってくるかわからない)
int (*(*fp)(int (*)(int, int), int))(int, int)
go
//変数
x int
p *int
a [3]int
//関数
func main(argc int, argv []string) int
とにかく「左から右」に読めるというのが利点とのこと.
型が複雑になっても読みやすい.
//最終的に帰ってくる型がわかりやすい
f func(func(int,int) int, int) int //intが帰ってくる
f func(func(int,int) int, int) func(int, int) int //関数ポインタが帰ってくる
ただし,ポインタの"*"(アスタリスク)だけはCと同様のルールになっているようです.
var p *int
x = *p
Golangの面白いと思った書き方
変数
//定数はconstで宣言.セイウチ演算子は使えない.
const World = "世界"
//変数を同時に複数代入できる(「初期化子initializerを与える」と言う)
var i, j int = 1, 2
//型は省略できる
var c, python, java = true, false, "no!"
//セイウチ演算子で暗黙的な型宣言ができる.(関数内のみ)
c, python, java := true, false, "no!"
//Goでは暗黙的な型変換は一切存在しない
var x, y int = 3, 4
fmt.Println(math.Sqrt(float64(x*x + y*y)))
//結果 : 5
//fmt.Println(math.Sqrt(x*x + y*y))
//結果 : cannot use x * x + y * y (type int) as type float64 in argument to math.Sqrt
Function
// 引数の型が同じ場合はまとめて書ける
func add(x, y int) int {
return x + y
}
//返り値を複数返せる(errorを返す場合などでありがち)
func swap(x, y string) (string, string) {
return y, x
}
// Named return value(長い関数では見づらくなるので注意)
func split(sum int) (x, y int) {
x = sum * 4 / 9
y = sum - x
return
}
if・for・switch
// ifの条件式を囲むカッコは不要.
// 変数宣言もできる.この変数はif・elseのスコープ内で有効.
if v := math.Pow(x, n); v < lim {
return v
} else {
fmt.Printf("%g >= %g\n", v, lim)
}
//forはCと同様,初期化ステートメント,条件式,後処理ステートメントを書く.
//Cと同じく,条件式だけあれば問題なく動作する.
for ; sum < 1000; {
sum += sum
}
//条件式のみの場合はセミコロン省略可能.
for ; sum < 1000; {
sum += sum
}
//条件すら省略すれば無限ループ
for {
sum += sum
}
//switch
// 条件は定数じゃなくても,intやstringでもOK
// フォールスルーしない(勝手にbreakしてくれる)
// 逆にフォールスルーしたい場合はfallthrough文を追加
switch os := runtime.GOOS; os {
case "darwin":
fmt.Println("OS X.")
fallthrough
case "linux":
fmt.Println("Linux.")
default:
// freebsd, openbsd,
// plan9, windows...
fmt.Printf("%s.\n", os)
}
//switch(true)は省略可能
switch {
case t.Hour() < 12:
fmt.Println("Good morning!")
case t.Hour() < 17:
fmt.Println("Good afternoon.")
default:
fmt.Println("Good evening.")
}
defer
//関数の実行をreturnまで遅延する(引数は即評価される)
func main() {
defer fmt.Println("world")
fmt.Println("hello")
//hello
//world
}
//deferの実行はスタック(LIFO)
func main() {
fmt.Println("counting")
for i := 0; i < 10; i++ {
defer fmt.Println(i)
}
fmt.Println("done")
}
/*
counting
done
9
8
7
6
5
4
3
2
1
0
*/