【第十四回Go言語学習備忘録】券売機システムを構築しつつパッケージについて理解する。

2月 12, 2022

どもです。chord number eightというアパレルブランドが推せるので是非チェックして欲しいsaisaiです。


今回はGolangを学習する上で必ず押さえておかなければならない、パッケージ、それからパブリック・プライベートという仕組みについて学びつつ、簡易券売機システムを作成してみました。


プログラミング学習歴1ヶ月の涙ぐましい努力ということで暖かい目でみていただければ幸いです。

パッケージとはなにか

これまで学習してきた中で、特に何も考えることなく"main.go"という名前のファイルを作成し、コード最初に"package main"と指定してしていました。しかしgolangでコードを作成する際に、パッケージとは何かについて理解しておくことは、複雑なコードをわかりやすく管理するためには重要なことです。


具体的にどのように扱っていくのか見ていきたいと思います。

パッケージ分けしてみる

パッケージとはつまるところディレクトリです。ディレクトリ名がそのままパッケージ名となります。なのでディレクトリ名(パッケージ名)はそこに格納しているGoファイルの役割がわかりやすいように設定しておくと良さそうです。

例えば、今回の券売機システムの場合は以下のような階層構造になっています。

venderFunctionというディレクトリの中にmain.goがあり、こちらがmainパッケージになります。さらに、venderFunctionの中には"total"ディレクトリがあり、さらにその中に"discount"というディレクトリがあります。つまり、mainパッケージ以外に"totalパッケージ"と"discountパッケージ"が存在するということになります。


今回は"チケットの合計金額を算出するgoファイル"を格納したtotalパッケージと、"日曜日には合計金額を10%割引するgoファイル"を格納したdiscountパッケージを作成しました。

合計金額の算出、パブリックとプライベート

それでは早速totalパッケージ内にgoファイルを用意してチケットの合計金額を算出する関数を作成してみましょう。

“simulation.go"というファイルを作成し、中にコードを記載していきます。

package total

func Calculation(v int) int {
	result := 2000 * v
	return result
}

今回はチケット一枚2000円という設定で関数を作成しました。枚数は引数vから定義し、合計金額を算出します。これでチケット合計金額の処理はtotalパッケージにて設定しているという状態になりました。


チケット一枚あたりの値段を変更する場合はtotalパッケージ内にある関数を修正すればよいといった具合に"修正箇所によってどこを修正すべきか"が判断しやすくなりましたね。


もう一つ着目すべきはCalculation関数の関数名の頭文字が大文字であるという点です。関数名を大文字にすることでこの関数を他のパッケージから呼び出すことができるようになります。このように外部から呼び出したり参照したりできる状態のものを"パブリック"といいます。


逆に関数名の頭文字を小文字にすると、その関数はパッケージ内でしか参照できません。これを"プライベート"と呼びます。

割引処理を行う関数の作成

続いて割引処理です。今回は購入日が日曜日だった場合、チケット代金が10%割引になるように設定していきます。discountパッケージ内に"special.go"というgoファイルを作成し、コードを以下の通り作成しました。

package discount

import (
	"fmt"
	"time"
)

func Holiday(v int) int {
	day := time.Now()
	weekday := day.Weekday()
	if weekday == 0 {
		fmt.Println("日曜日は10%割引!")
		charge := float64(v) * 0.9
		return int(charge)
	} else {
		charge := v
		return charge
	}
}

曜日に応じて割引処理をおこなうHoliday関数を作成しました。初心者なので少し無理やり感が否めません…が上記のコードで詰まったところをいくつか紹介させていただきます。

day := time.Now()
	weekday := day.Weekday()
	if weekday == 0

こちらは"購入日(今日)が日曜日なら"という部分です。Weekdayメソッドで出力される曜日には数字が割り振られており、その数字をint型として演算処理を行うことができます。例えば今回の場合、日曜日には"0″という数字が割り振られていますから

if weekday == 0

とすることで今日が日曜日かそうではないかのif文を作成することができます。

さらに割引の部分ですが、今回は以下のようにしました。

charge := float64(v) * 0.9
return int(charge)

小数点の計算にはfloat型を使用しますが、返り値はint型で指定していることから型変換を使用して無理やり成立させました(笑)。もっといい方法がありそうです…。

これで曜日や割引率など割引に関する設定はdiscountパッケージで行っているという状態をつくることができました。

このように処理の目的などに応じてパッケージ分けすることで内容を把握しやすく、カスタマイズ性に長けたコードを作成することが可能となります。

main関数の作成

それではいよいよmain関数を作成していきたいと思います。先に今回作成したmain関数を置いておきます。

package main

import (
	"fmt"
	"ticketVender/venderFunction/total"
	"ticketVender/venderFunction/total/discount"
)

var num int

func main() {
	fmt.Println("チケットは一枚2000円です。")
	fmt.Printf("チケットの枚数を選択してください:")
	fmt.Scan(&num)
	normal := total.Calculation(num)
	special := discount.Holiday(normal)
	if special == 0 {
		fmt.Println("枚数が正しくありません ,もう一度やり直してください")
	} else {
		fmt.Printf("合計金額は[%v]円です。\n", special)
	}
}

scanner(fmt.Scan)はインタラクティブな処理を可能にします。コードを実行したあと、数値が入力されるまで待機します。

saisai %  go run main.go
チケットは一枚2000円です。
チケットの枚数を選択してください:(数値が入力されるまで待機)

数値を入力すると変数"num"のアドレス値にその数値が格納されます。

次に、格納された数値を引数としてtotalパッケージのCalculation関数を実行しましょう。まずは外部パッケージであるtotalパッケージをインポートします。

import (
"ticketVender/venderFunction/total"

このようにターゲットパッケージまでのパスを指定することで、インポート出来ます。これでtotalパッケージ内でパブリックに作成した関数やメソッド、構造体などが使用できるようになりました。それではCalculation関数を実行してみましょう。

normal := total.Calculation(num)

外部パッケージから引用する場合は上記のように"パッケージ名.関数名など"で指定します。引数にはscannerで取得した値が格納されている変数numを指定しましょう。変数normalを定義し、Calculation関数の値を代入できるようにします。これでチケットの合計金額が変数normalに代入されました。


続いて割引の部分です。Holiday関数を実行しましょう。引数には合計金額が格納されている変数normalを指定します。これでnormalに格納された値を日曜日なら10%引きに、そうでない場合はそのまま返してくれますので変数specialを定義してその値を代入します。


あとは変数specialを出力するのみです!

if special == 0 {
		fmt.Println("枚数が正しくありません ,もう一度やり直してください")
	} else {
		fmt.Printf("合計金額は[%v]円です。\n", special)
	}

scannerで値を取る際、数値(int型)以外の値を入力した場合はspecialの値は0になります。おそらくですが、値がint型以外の場合、Calculation関数の引数がintの初期値である0で実行されるためだと思われます。そのため、変数specialの値として0が出力された場合は入力した値が正しくないという内容を出力するようにしました。


int型の数値を正しく入力した場合は、合計金額あるいは割引された金額が出力されます。実行結果は以下の通り。

saisai % go run main.go
チケットは一枚2000円です。
チケットの枚数を選択してください:2
合計金額は[4000]円です。

saisai % go run main.go
チケットは一枚2000円です。
チケットの枚数を選択してください:2
日曜日は10%割引!
合計金額は[3600]円です。

無事、割引もされていますね!

ひとこと

今回はパッケージの使用方法を学びつつ、券売機システムを作成してみました!


ちなみにimportするパッケージはGOPATHを参考に探しに行くので、パッケージはGOPATHを参照して正しい場所に作成する必要があります。GOPATHに指定するパスの変更も出来ますので、設定方法を調べつつ自身にあった環境を構築しておきましょう。以下の記事が分かりやすくお勧めです。

【Golang】独自パッケージのインポート

コード可読性や管理しやすさなどを考慮すると、パッケージを使いこなすスキルは必須と言えそうです。アプリケーションをどんどん開発し、より複雑な階層構造でもしっかりパッケージ分けできるようになりたいと思います。

ここまで読んでいただきありがとうございました!


-saisai-


↓本日のオススメ教材

Golang

Posted by CY