はじめに
A Tour of GoでGo言語の基本を学んでみましたが、言葉や具体例がいまいち分かりづらい部分もあったため、自分なりにまとめました。 (今の自分のレベルに対する備忘録の側面が強いため、逆に分かりにくい部分もあるかもしれません…)
これはパート1です。
- 基本的なプログラムの書き方とimportの方法
- print文の基本
- 関数の基本(Functions)
- 変数の宣言(Variables)
- 定数の使い方
- for と if と switch
- 参考
- 続きは…
基本的なプログラムの書き方とimportの方法
Goのプログラムは、全てパッケージに属している必要があります。
最初にPackageを作成して、それをmainで実行させる流れです。
そのため、コードの最初にpackage main
がないとエラーになります。
// これがないとエラーになる package main // functionとしてmainを書き、その中に実行させたい処理を書く func main() { (処理を書く) }
別のパッケージを使う場合は、下記のようにimportします。
package main // import文 import ( "fmt" "math" ) func main() { (処理を書く) }
import文は分けて書くこともできますが、()で囲った方が読みやすくなります。
import "fmt" import "math"
例えばmath
パッケージは下記のように使います。
package main import ( "fmt" "math/rand" ) func main() { fmt.Println("ランダム数値:", rand.Int()) }
ここではランダムな数値が出力されます。
出力例:
ランダム数値: 12345
rand.Int()
のようにimportしたパッケージのメソッドを使う時は、頭文字を大文字にする必要があります。
小文字のパッケージは内部用として使うことになっており、外部からはアクセスできないようになっているため、自分でパッケージを作成し、他のプログラムから利用するときには注意が必要です。
下記公式ページにて言及されています。
The Go Programming Language Specification - The Go Programming Language
同じパッケージに属するファイル間では、importの必要なく変数や関数を自由に利用できます。
その代わり、同一のディレクトリに格納し、名前の重複を避ける必要があります。また、同一ディレクトリに別のパッケージを格納することはできません。
src
┣ processing
┃ ┣ code1.go
┃ ┗ code2.go
┗ getdata
┗ code3.go
code1.go
package processing func merge(){ 処理… }
code2.go
package processing func Replace(){ merge() 処理… }
code3.go
package getdata import "processing" func getCsv(){ // merge() // エラーになる // processing.merge() // 小文字の関数にはアクセスできないためエラーになる processing.Replace() }
print文の基本
Println, Printf
fmtパッケージにてprint文が用意されています。
fmt.Println
を使うことで、最後に改行されてprintされます。
fmt.Printf
を使うことで%を使って出力ができます。
fmt.Println(math.Sqrt(7)) // 49が出力され、改行される fmt.Printf("4のルートは、 %g です。", math.Sqrt(4)) // 2が出力される
fmt.Print
でもprintできますが、改行されず、%も使えません。
fmt.Printf("4のルートは、 %g です。", math.Sqrt(4))
上記の出力は、
4のルートは、 %g です。2
となってしまいます。
ちなみに%g
は、浮動小数点数(float64など)や複素数(complex128など)の時に利用します。%t
は論理値(bool)、%d
は整数(int, int8, uint, uint8など)、%s
は文字列(string)として使えます。
Sprintln, Sprintf
fmt.Sprintf
とfmt.Sprintln
は挙動は上記2つとほぼ同じですが、標準出力するのではなく、stringをreturnしてくれます。そのため%d
などを使った結果を変数に格納したり、ファイルに保存したりできるようになります。
result_string1 := fmt.Sprintf("4のルートは、 %g です。", math.Sqrt(4)) result_string2 := fmt.Sprintf("9のルートは、 %g です。", math.Sqrt(9)) fmt.Println(result_string1, result_string2)
下記のように出力されます。
4のルートは、 2 です。 9のルートは、 3 です。
仕様は以下です。
fmt package - fmt - pkg.go.dev
関数の基本(Functions)
関数の書き方は以下のようになります。
func 関数名( 変数 型, 変数 型, …) 返り値の型 {
関数の中身
}
変数名の後ろに型を書くところが他の言語と異なる点です。
いくつか例を見てみます。
package main import "fmt" // 2つの引数を足す関数 func add(x int, y int) int { return x + y } // 2つの引数を掛ける関数 func mul(x, y int) int { return x * y} // 文字を入れ替える関数 func swap(x, y string)(string, string){ return y, x } func main(){ fmt.Println(add(3, 4)) // 7 fmt.Println(mul(3, 4)) // 12 fmt.Println(swap("first", "second")) // second first }
mul関数のように、同じTypeが続く場合には省略して書くこともできます。
func add(x int, y int) ↓ func add(x, y int)
swap関数のように返り値を複数設定することもできます。
func swap(x, y string)(string, string){ return y, x }
下記のように事前に変数をつけて返り値を設定することで、return文には何も書かなくてOKになります。
package main import "fmt" func sumave(x, y int) (sum, ave int){ sum = x + y ave = (x + y) /2 return } func main(){ fmt.Println(sumave(5, 9)) // 14 7 }
ただし、長い関数で使うと読みにくくなるため、短いわかりやすい関数でのみ使うべきです。また、例えばswap関数をreturn文なしで実装しようとして、下記のように引数と返り値で同じ変数を使うと、エラーになってしまいますのでご注意ください。
func swap(x, y string)(y, x string) { return }
duplicate argument
というエラーが発生します。
変数の宣言(Variables)
変数はvarを使って宣言することで使えます。
package main import "fmt" // 基本的にはvarと型で挟みます var flag bool var moji string var i int // 初期値を設定した場合は型を自動で判別してくれます var num, word = 2, "hello" // importと同様にまとめて宣言することもできます var ( hoge = "fuga" geho = "gafu" ) func main() { fmt.Println(flag, moji, i, num, word, hoge, geho) }
出力は下記になります。
false 0 2 hello fuga gafu
初期値を何も設定していない場合は、型に沿ったデフォルト値が入ります。(上記の結果でいうと、falseと0の間に実は空白があります。)
各型に対するデフォルト値は下記です。
- bool: false
- string: 空文字列
- int: 0
関数の中では、省略した形で変数を宣言できます。varと型を書かずに:=を使って定義するだけです。
package main import "fmt" func main(){ num := 3 fmt.Println(num) // 3 }
ただし、関数の外ではこの省略形は使えず、エラーになります。
package main import "fmt" num := 3 func main(){ fmt.Println(num) // 3 }
上記のようにmain関数の外で変数を定義すると、
syntax error: non-declaration statement outside function body
というエラーが出ます。外で定義したい場合は、var num = 3
とする必要があります。
定数の使い方
定数はconstを使って宣言できます。ただし、:=による宣言はできません。(変数として扱われます。)
package main import "fmt" const Pi = 3.14 func main() { const user = "太郎" num := 3 // 変数扱いになる // user = "次郎" // cannot assign to userというエラーになる num = 5 // これはエラーにならない、つまり変数 fmt.Println("Hello", user) fmt.Println("Luckey number:", num) }
出力は、
Hello 太郎 Luckey number: 5
になります。
for と if と switch
for
for
ループはC言語などと同じくセミコロン ;
で3つの部分に分けて書きます。
for 初期化 ; 条件式 ; 後処理 { ループ処理 }
例えば、下記のように書きます。
func main() { sum := 0 for i := 0; i < 10; i++ { sum += i } fmt.Println(sum) }
初期化と後処理の部分は省略可能です。
sum := 1 for ; sum < 100; { sum += sum
セミコロンすら省略可能ですので、while文をforを使って表現できます。
sum := 1 for sum < 100 { sum += sum }
if
基本的な書き方は他の言語とほぼ同じです。
func checkNum(x int) string { if x < 0 { return "minus" } else if x > 0 { return "plus" } else { return "zero" } } func main() { fmt.Println(checkNum(4)) }
条件の前に、変数の定義を書くことができます。ただし、その変数のスコープはif文の中だけです。
if v := math.Pow(x, n); v < limmit { // Powはべき乗の計算 処理 }
switch
条件に一致したcaseのみを実行します。そのため、break文は不要です。どのcaseにも当てはまらなければdefaultが実行されます。
例えば下記のように使います。
func main() { fmt.Println("When's Saturday?") today := time.Now().Weekday() switch time.Saturday { case today + 0: fmt.Println("Today.") case today + 1: fmt.Println("Tomorrow.") case today + 2: fmt.Println("In two days.") default: fmt.Println("Too far away.") } }
条件を省略することも可能です。
func main() { t := 10 switch { case t < 10: fmt.Println("A digit") case t < 100: fmt.Println("Double-digits") default: fmt.Println("Over three digits") } }
上記の例はif文でも表現可能です。
func main() { t := 10 if t < 10 { fmt.Println("A digit") } else if t < 100 { fmt.Println("Double-digits") } else { fmt.Println("Over three digits") } }
参考
続きは…
part2はこちらです↓