🧾

Goで請求書システムを実装する【入門】

に公開

はじめに

Go言語とは?

Go(Golang)は、Googleが開発したオープンソースのプログラミング言語で、シンプルさ、効率性、並行性のサポートを特徴としています。オブジェクト指向の概念(クラスなど)はありませんが、構造体(struct)とメソッドを使うことで柔軟にプログラムを設計できます。

このプロジェクトで学べること

このプロジェクトでは、Goを使用して請求書管理システムを構築します。以下のポイントを学びます。

  • Goの構造体(struct)の使い方
  • メソッドと関数を使った設計
  • JSON形式でのデータ操作
  • Web APIの基礎(Ginフレームワークを使用)
  • ファイル保存

請求書システムの設計

システムの概要

この請求書システムは以下の要素で構成されます:

  1. 顧客情報(Customer)
    • 名前、住所、メールアドレス
  2. 請求項目(InvoiceItem)
    • 商品やサービスの詳細(名称、単価、数量)
  3. 請求書(Invoice)
    • 顧客情報と請求項目をまとめ、合計金額を算出

コード実装

プロジェクトの準備

新しいGoプロジェクトを作成します。

mkdir invoice-system
cd invoice-system
go mod init invoice-system

顧客情報(Customer)

顧客情報を管理するための構造体を定義します。

package main

type Customer struct {
    Name    string
    Address string
    Email   string
}

請求項目(InvoiceItem)

請求項目を管理する構造体を作成し、各項目の小計を計算するメソッドを追加します。

type InvoiceItem struct {
    Description string
    UnitPrice   float64
    Quantity    int
}

// 小計を計算するメソッド
func (item InvoiceItem) Total() float64 {
    return item.UnitPrice * float64(item.Quantity)
}

請求書(Invoice)

請求書全体を管理する構造体を作成し、合計金額を計算するメソッドを追加します。

type Invoice struct {
    Customer     Customer
    Items        []InvoiceItem
    InvoiceTotal float64
}

// 合計金額を計算するメソッド
func (inv *Invoice) CalculateTotal() {
    var total float64
    for _, item := range inv.Items {
        total += item.Total()
    }
    inv.InvoiceTotal = total
}

メイン関数で請求書を生成

これまでに定義した構造体を使って、請求書を生成します。

package main

import "fmt"

func main() {
    // 顧客情報を作成
    customer := Customer{
        Name:    "Haruki",
        Address: "TOKYO",
        Email:   "zenn@sample.com",
    }

    // 請求項目を作成
    items := []InvoiceItem{
        {Description: "Web開発サービス", UnitPrice: 150000, Quantity: 1},
        {Description: "保守サポート", UnitPrice: 30000, Quantity: 3},
    }

    // 請求書を作成
    invoice := Invoice{
        Customer: customer,
        Items:    items,
    }

    // 合計金額を計算
    invoice.CalculateTotal()

    // 請求書を表示
    fmt.Printf("請求書\n顧客: %s\n住所: %s\nメール: %s\n\n",
        invoice.Customer.Name, invoice.Customer.Address, invoice.Customer.Email)
    fmt.Println("請求項目:")
    for _, item := range invoice.Items {
        fmt.Printf("- %s: ¥%.2f x %d = ¥%.2f\n",
            item.Description, item.UnitPrice, item.Quantity, item.Total())
    }
    fmt.Printf("\n合計金額: ¥%.2f\n", invoice.InvoiceTotal)
}

実行結果

保存したファイルを実行して、正しい出力が得られるか確認します。

go run main.go

出力例:

請求書
顧客: Haruki
住所: TOKYO
メール: zenn@sample.com

請求項目:
- Web開発サービス: ¥150000.00 x 1 = ¥150000.00
- 保守サポート: ¥30000.00 x 3 = ¥90000.00

合計金額: ¥240000.00

応用機能

請求書の保存

請求書をファイルに保存して、後で参照できるようにします。

テキスト形式で保存

import (
    "os"
    "fmt"
)

func (inv Invoice) SaveToTextFile(filename string) error {
    file, err := os.Create(filename)
    if err != nil {
        return err
    }
    defer file.Close()

    content := fmt.Sprintf("請求書\n顧客: %s\n住所: %s\nメール: %s\n\n",
        inv.Customer.Name, inv.Customer.Address, inv.Customer.Email)
    content += "請求項目:\n"
    for _, item := range inv.Items {
        content += fmt.Sprintf("- %s: ¥%.2f x %d = ¥%.2f\n",
            item.Description, item.UnitPrice, item.Quantity, item.Total())
    }
    content += fmt.Sprintf("\n合計金額: ¥%.2f\n", inv.InvoiceTotal)

    _, err = file.WriteString(content)
    return err
}

JSON形式で保存

import (
    "encoding/json"
    "os"
)

func (inv Invoice) SaveToJSONFile(filename string) error {
    file, err := os.Create(filename)
    if err != nil {
        return err
    }
    defer file.Close()

    encoder := json.NewEncoder(file)
    return encoder.Encode(inv)
}

Web API化

Ginフレームワークを使って請求書生成APIを実装します。

import (
    "github.com/gin-gonic/gin"
    "net/http"
)

func main() {
    r := gin.Default()

    r.POST("/invoice", func(c *gin.Context) {
        var invoice Invoice
        if err := c.ShouldBindJSON(&invoice); err != nil {
            c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
            return
        }

        invoice.CalculateTotal()
        c.JSON(http.StatusOK, invoice)
    })

    r.Run(":8080")
}

最後に

このプロジェクトを通じて、Goの構造体、メソッド、JSON操作、Web API、ファイル保存などを学びました。これを基に、さらに高度な機能を実装して実用的な請求書システムを作りましょう!

Discussion