この記事では、Go言語の関数(func)の定義方法について、プログラミング初心者の方にも分かりやすく解説を進めます!
Go言語を学び始めたばかりだと、「関数って何だかむずかしそう…」「`func`ってどう書くの?」なんて思うかもしれませんね。
関数は、プログラムを整理整頓するための超便利アイテム。同じような処理を何度も書く手間を省いてくれる、いわば「プログラムのお助けパーツ」なんです。
この記事を読むと、こんなことができるようになります。
- Go言語の関数がどういうものか説明できる
- `func`キーワードを使った基本的な関数の定義ができる
- 関数に情報を渡す「引数」の使い方がわかる
- 関数から結果を受け取る「戻り値」の使い方がわかる
- 簡単なサンプルコードを読んで、自分で関数を作ってみる
- 関数定義でハマりがちなポイントを知って、エラーを避けられる
Go言語における関数 (func) とは?
まず、Go言語における「関数」って一体何者なのか、そこから見ていきましょう。
難しく考えなくてOKです。関数とは、一連の処理をひとまとめにした「かたまり」のこと。イメージとしては、料理のレシピみたいなものかもしれません。
例えば、「卵を割って、かき混ぜて、フライパンで焼く」という一連の手順を「卵焼きを作る」という名前(関数名)でまとめておけば、次からは「卵焼きを作る」と指示するだけで済みますよね。
プログラムでも同じで、特定の目的を持った処理の集まりに名前をつけて、何度も呼び出して使えるようにしたものが関数です。Go言語では、この関数を定義するために`func`というキーワードを使います。
関数を使うメリットはたくさんあります。
- 再利用できる
同じ処理を何度も書かなくて済むので、コードがスッキリします。 - 分かりやすくなる
処理に名前がついているので、何をしているのか理解しやすくなります。 - 修正が楽になる
もし処理内容を変更したくなっても、その関数の中だけ直せばOKです。
プログラムが大きくなればなるほど、この関数のありがたみが身にしみてきますよ。だから、Go言語を学ぶ上で、この関数定義は避けて通れない、基本中の基本スキルなんです。
Go言語の関数定義 (func) の基本的な書き方
それでは、いよいよGo言語で関数を定義する具体的な書き方を見ていきましょう。
一番シンプルな形は、引数(関数に渡す情報)も戻り値(関数から返ってくる結果)もない関数です。
基本形はこんな感じです。
func 関数名() { // ここに関数が行う処理を書く }
各部分を分解してみましょう。
func
これは「これから関数を定義しますよ~」というGo言語への合図です。必ず最初に書きます。関数名
あなたが自由につけられる関数の名前です。どんな処理をする関数なのか、分かりやすい名前をつけるのがコツです。()
このカッコは、関数に情報を渡す「引数」を指定する場所ですが、今は何も渡さないので空っぽです。でも、カッコ自体は省略できません。{}
この波カッコの中に、実際に行わせたい処理を書いていきます。
例えば、画面に「Hello, Go Function!」と表示するだけの簡単な関数を作ってみましょう。
package main import "fmt" // あいさつを表示する関数を定義 func sayHello() { fmt.Println("Hello, Go Function!") } func main() { // 定義した関数を呼び出す sayHello() }
この例では、sayHello
という名前の関数を定義して、main
関数の中から呼び出しています。main
関数も実はGo言語の特別な関数の一つなんですよ。
`func`キーワードと関数名のルール
関数定義の基本がわかったところで、もう少し詳しくfunc
キーワードと関数名のルールについて補足します。
func
キーワードは、先ほど説明した通り、関数定義の開始を宣言するものです。これはGo言語の決まりなので、おまじないのように覚えてください。
次に関数名のルールです。これにはいくつか慣習的な決まりがあります。
- 使える文字
基本的に半角の英数字とアンダースコア(`_`)が使えます。ただし、数字から始めることはできません。 - 命名規則(キャメルケース)
Go言語では、複数の単語をつなげる場合、calculateTotalPrice
のように、単語の先頭を大文字にする「キャメルケース」がよく使われます。(最初の単語は小文字から始めるのが一般的です) - 大文字・小文字の意味
これがGo言語の特徴的な部分! 関数名の最初の文字が大文字か小文字かで、その関数が他のパッケージ(プログラムの部品のまとまり)から呼び出せるかどうかが決まります。- 大文字始まり (例:`PublicFunction`) 他のパッケージからも呼び出せる、公開された関数になります(エクスポートされる、と言います)。
- 小文字始まり (例:`privateFunction`) その関数が定義されたパッケージ内からしか呼び出せない、内部的な関数になります。
最初は小文字始まりの関数から作っていくことが多いでしょう。分かりやすく、他の人が読んでも意味が通じる名前をつけることを心がけてみてくださいね。
Go言語の関数定義 (func) で引数を使ってみよう
先ほどのsayHello
関数は、いつも同じメッセージを表示するだけでした。
でも、関数にもっと柔軟な動きをさせたい場合もありますよね。例えば、「こんにちは、〇〇さん!」のように、呼び出すたびに違う名前を表示したい場合などです。
そんな時に使うのが引数(ひきすう)です。引数は、関数を呼び出すときに、外部から関数へ情報を渡すための仕組みです。
引数を使うには、関数定義の()
の中に、受け取りたい情報の「名前」と「型」を書きます。
func 関数名(引数名1 型1, 引数名2 型2) { // 引数を使った処理を書く }
例えば、名前を受け取ってあいさつする関数は、こんな風に書けます。
package main import "fmt" // 名前(string型)を引数として受け取る関数 func greet(name string) { fmt.Println("こんにちは、" + name + "さん!") } func main() { // 関数を呼び出すときに、引数として具体的な名前を渡す greet("太郎") greet("花子") }
実行結果はこうなります。
こんにちは、太郎さん! こんにちは、花子さん!
greet("太郎")
のように関数を呼び出すとき、"太郎"
という文字列がgreet
関数のname
という変数に渡され、関数の中で使われています。引数を使うことで、関数がぐっと便利になるのが分かりますね!
引数の基本的な定義方法
引数の基本的な定義パターンをいくつか見ておきましょう。
1. 引数が1つの場合
先ほどのgreet
関数のように、(引数名 型)
と書きます。
func printAge(age int) { fmt.Println("年齢は", age, "歳です。") }
2. 引数が複数で、型が異なる場合
カンマ(,
)で区切って、それぞれの引数名と型を書きます。
func printProfile(name string, age int) { fmt.Println("名前:", name, "年齢:", age) }
3. 引数が複数で、型が同じ場合
これがちょっと便利な書き方! 連続する引数の型が同じなら、最後の引数だけに型を書けばOKです。
// xもyもint型 func add(x, y int) { fmt.Println(x + y) }
これはfunc add(x int, y int)
と書くのと同じ意味になります。コードが少し短くなりますね。
関数を呼び出すときは、定義した順番通りに値を渡してあげてください。
printProfile("次郎", 30) // nameに"次郎", ageに30が渡る add(5, 3) // xに5, yに3が渡る
引数の型と、渡す値の型が合っていないとエラーになるので気をつけてくださいね。
Go言語の関数定義 (func) で戻り値を使ってみよう
関数に情報を渡す「引数」の次は、関数から情報を受け取る戻り値(もどりち)または返り値(かえりち)について学びましょう。
関数は、何か処理を行った結果を、呼び出し元に返すことができます。例えば、2つの数値を足し算する関数なら、その計算結果を返してほしいですよね。
戻り値を使うには、関数定義の()
の後ろに、返す値の「型」を書きます。
func 関数名(引数リスト) 戻り値の型 { // 処理... return 返す値 // return文で値を返す }
そして、関数の中では`return`というキーワードを使って、実際に値を返します。
単一の戻り値の定義
まずは、戻り値が1つの場合を見てみましょう。先ほどの足し算の例です。
package main import "fmt" // 2つのint型引数を受け取り、合計値(int型)を返す関数 func add(x, y int) int { // ()の後ろに戻り値の型intを書く sum := x + y return sum // 計算結果のsumを返す } func main() { result := add(10, 5) // add関数の戻り値をresult変数で受け取る fmt.Println("計算結果:", result) // 15と表示される }
実行結果
計算結果: 15
ポイントは、func add(x, y int) int
のように、引数のカッコ()
の後ろに戻り値の型を書くこと。そして、関数内でreturn sum
として、計算結果(sum
)を返しています。呼び出し元のmain
関数では、result := add(10, 5)
のようにして、返ってきた値を変数result
で受け取っていますね。
return
で返す値の型は、関数定義で指定した戻り値の型と一致させる必要があります。
複数の戻り値の定義
Go言語の面白い特徴の一つが、関数が複数の値を同時に返すことができる点です!他のプログラミング言語ではあまり見られない機能かもしれません。
複数の値を返すには、戻り値の型をカッコ()
で囲んで、カンマ区切りで指定します。
func 関数名(引数リスト) (戻り値の型1, 戻り値の型2) { // 処理... return 返す値1, 返す値2 }
これは、特に関数が成功したかの情報と結果を一緒に返したい場合や、エラー情報を一緒に返したい場合などにとても便利です。
例えば、割り算をする関数を考えてみましょう。割り算は、0で割ろうとするとエラーになりますよね。そこで、計算結果とエラー情報を一緒に返す関数を作ってみます。
package main import ( "fmt" "errors" // エラーを扱うためのパッケージ ) // 2つのfloat64型を受け取り、結果(float64)とエラー(error)を返す関数 func divide(a, b float64) (float64, error) { // 戻り値の型を(float64, error)と指定 if b == 0 { // 0除算の場合は、エラーを返す return 0, errors.New("0で割ることはできません") } // 正常な場合は、計算結果とnil(エラーなし)を返す return a / b, nil } func main() { // 正常な場合 result1, err1 := divide(10.0, 2.0) if err1 != nil { fmt.Println("エラー:", err1) } else { fmt.Println("結果1:", result1) // 結果1: 5 } // エラーが発生する場合 result2, err2 := divide(5.0, 0) if err2 != nil { fmt.Println("エラー:", err2) // エラー: 0で割ることはできません } else { fmt.Println("結果2:", result2) } // 戻り値の一部だけ使いたい場合は、_(アンダースコア)で無視できる result3, _ := divide(12.0, 3.0) fmt.Println("結果3:", result3) // 結果3: 4 }
実行結果
結果1: 5 エラー: 0で割ることはできません 結果3: 4
このdivide
関数は、(float64, error)
という2つの戻り値を持っています。呼び出し側では、result1, err1 := divide(10.0, 2.0)
のように、カンマ区切りで2つの変数を用意して受け取ります。もしエラーがなければerr1
にはnil
(何もない、という意味)が入り、エラーがあれば具体的なエラー情報が入ります。
もし片方の戻り値しか必要ない場合は、_
(アンダースコア、ブランク識別子と呼ばれます)を使って、受け取らないようにできます。これはGo言語でよく使われるテクニックです。
Go言語の関数定義 (func) の実践的な使い方
さあ、これまでの知識を総動員して、もう少しだけ実践的なサンプルプログラムを見てみましょう!引数と戻り値を使った簡単な関数を定義し、それをmain
関数から呼び出してみます。
長方形の面積を計算する
package main import "fmt" // 長方形の縦(height)と横(width)を受け取り、面積(area)を返す関数 func calculateRectangleArea(height, width float64) float64 { area := height * width return area } func main() { // 関数の呼び出し1 h1 := 5.0 w1 := 10.0 area1 := calculateRectangleArea(h1, w1) // 関数を呼び出して面積を計算 fmt.Printf("縦%.1f, 横%.1f の長方形の面積: %.1f\n", h1, w1, area1) // 関数の呼び出し2 h2 := 7.5 w2 := 3.0 area2 := calculateRectangleArea(h2, w2) fmt.Printf("縦%.1f, 横%.1f の長方形の面積: %.1f\n", h2, w2, area2) }
実行結果
縦5.0, 横10.0 の長方形の面積: 50.0 縦7.5, 横3.0 の長方形の面積: 22.5
コード解説
package main
とimport "fmt"
はお決まりの記述ですね。func calculateRectangleArea(height, width float64) float64
ここで関数を定義しています。calculateRectangleArea
が関数名。(height, width float64)
は、height
とwidth
という2つのfloat64
型(小数点数を扱える型)の引数を受け取ることを示します。同じ型なので、型指定は最後にまとめています。- 最後の
float64
は、この関数がfloat64
型の値を返す(戻り値)ことを示しています。
area := height * width
関数の中で、受け取ったheight
とwidth
を掛け合わせて面積を計算し、area
変数に代入します。return area
計算した面積area
を関数の結果として返します。func main()
プログラムの実行開始点です。area1 := calculateRectangleArea(h1, w1)
ここで定義したcalculateRectangleArea
関数を呼び出しています。引数としてh1
(5.0)とw1
(10.0)を渡し、返ってきた結果(面積 50.0)をarea1
変数に代入しています。fmt.Printf(...)
計算結果を表示しています。%.1f
は、小数点以下1桁まで表示するという意味です。- 同様に、2回目の関数呼び出しと結果表示を行っています。
このように、関数を定義しておけば、同じ計算処理を何度も書かずに、関数を呼び出すだけで済むようになります。コードがスッキリして、読みやすくなりましたね!
Go言語の関数定義 (func) における注意点
関数定義はとても便利ですが、いくつか気をつけたいポイントがあります。初心者のうちにつまずきやすい点を挙げておきますね。
関数名の重複
引数の型と数
戻り値の型と`return`文
未使用変数エラー
_
(アンダースコア)に代入するなどして、未使用状態を解消する必要があります。大文字・小文字の違い
エラーが出ても焦らないで!エラーメッセージをよく読むと、どこがおかしいのかヒントが書かれていることが多いです。「undefined: 関数名」なら関数が見つからない、「too many arguments」なら引数が多すぎる、といった具合です。少しずつ慣れていきましょう。
【まとめ】Go言語の関数定義 (func) を活用しよう
お疲れ様でした!今回はGo言語の関数定義(`func`)について、基本的なところから引数、戻り値、そして実際の使い方まで一通り見てきました。
最後に、今回のポイントをまとめておきましょう。
- 関数は、処理をまとめた部品のようなもの。
func
キーワードで定義する。 - 関数名は分かりやすい名前をつけ、最初の文字が大文字か小文字かで公開範囲が変わる。
( )
の中に引数を定義すると、関数に情報を渡せる。( )
の後ろに戻り値の型を書くと、関数から結果を受け取れる。Goは複数の戻り値も扱える!return
文で、関数から値を返す。- 関数を使うと、コードが整理され、再利用しやすくなる。
関数を使いこなせるようになると、書けるプログラムの幅がぐんと広がります。最初は少し戸惑うかもしれませんが、今回学んだことを元に、ぜひ色々な関数を自分で定義して、動かしてみてください。
小さな成功体験を積み重ねることが、上達への一番の近道です!
【関連記事】 Go言語とは?特徴・できること・将来性
0 件のコメント:
コメントを投稿
注: コメントを投稿できるのは、このブログのメンバーだけです。