はじめに
現在の部署に入ってから、Goでのファイル操作ばかりを行なっているので、この記事では、Goでの色々なファイルの読み書きについて説明します。
JSON
inputファイル
input.json
{
"name": "John",
"age": 30
}
読み込みサンプルコード
main.go
package main
import (
"encoding/json" // JSONエンコード/デコード用パッケージ
"fmt" // フォーマット済み入出力用パッケージ
"log" // ログ出力用パッケージ
"os" // ファイル操作などのOS機能用パッケージ
)
// User構造体はJSONデータのユーザー情報を表現します
type User struct {
Name string `json:"name"` // JSONの"name"キーに対応
Age int `json:"age"` // JSONの"age"キーに対応
}
const filePath = "input.json" // 読み込むJSONファイルのパス
func main() {
// 読み込み専用でファイルをオープン
file, err := os.Open(filePath)
if err != nil {
log.Fatal(err) // エラー発生時はログ出力して終了
}
defer file.Close() // 関数終了時にファイルを必ずクローズ
var user User
// JSONデコーダーでファイルの内容をUser構造体にデコード
if err := json.NewDecoder(file).Decode(&user); err != nil {
log.Fatal(err) // デコードエラーがあればログ出力して終了
}
// デコードしたユーザー情報を出力
fmt.Printf("%+v\n", user) // {Name:John Age:30}
}
書き込みサンプルコード
main.go
package main
import (
"encoding/json" // JSONのエンコード/デコード用パッケージ
"log" // エラーログ出力用パッケージ
"os" // ファイル操作などのOS機能用パッケージ
)
// User構造体はユーザー情報を保持します
type User struct {
Name string `json:"name"` // JSONの"name"キーに対応
Age int `json:"age"` // JSONの"age"キーに対応
}
const filePath = "output.json" // 出力ファイルのパス
func main() {
// 書き込み可能な状態でファイルをオープン(存在しなければ作成、存在すれば内容を上書き)
file, err := os.OpenFile(filePath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
if err != nil {
log.Fatal(err) // エラー発生時はログ出力して終了
}
defer file.Close() // 関数終了時にファイルを必ずクローズ
// 書き込むユーザー情報を定義
user := User{
Name: "John",
Age: 30,
}
// json.Encoderを使って、ユーザー情報をJSON形式でファイルに書き込む
if err := json.NewEncoder(file).Encode(user); err != nil {
log.Fatal(err) // エンコードまたは書き込みエラーの場合、ログ出力して終了
}
}
YAML
inputファイル
input.yaml
name: John
age: 30
読み込みサンプルコード
main.go
package main
import (
"fmt" // フォーマット済み入出力用パッケージ
"log" // ログ出力用パッケージ
"os" // ファイル操作用パッケージ
"gopkg.in/yaml.v3" // YAMLエンコード/デコード用パッケージ
)
// User構造体はYAMLデータのユーザー情報を表現します
type User struct {
Name string `yaml:"name"` // YAMLの"name"キーに対応
Age int `yaml:"age"` // YAMLの"age"キーに対応
}
const filePath = "input.yaml" // 読み込むYAMLファイルのパス
func main() {
// 読み込み専用でファイルをオープン
file, err := os.Open(filePath)
if err != nil {
log.Fatal(err)
}
defer file.Close()
var user User
// YAMLデコーダーでファイルの内容をUser構造体にデコード
if err := yaml.NewDecoder(file).Decode(&user); err != nil {
log.Fatal(err)
}
// デコードしたユーザー情報を出力
fmt.Printf("%+v\n", user) // {Name:John Age:30}
}
書き込みサンプルコード
main.go
package main
import (
"log" // エラーログ出力用パッケージ
"os" // ファイル操作用パッケージ
"gopkg.in/yaml.v3" // YAMLエンコード/デコード用パッケージ
)
// User構造体はユーザー情報を保持します
type User struct {
Name string `yaml:"name"` // YAMLの"name"キーに対応
Age int `yaml:"age"` // YAMLの"age"キーに対応
}
const filePath = "output.yaml" // 書き込み先のYAMLファイルパス
func main() {
// 書き込み可能な状態でファイルをオープン(存在しなければ作成、存在すれば上書き)
file, err := os.OpenFile(filePath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
if err != nil {
log.Fatal(err)
}
defer file.Close()
user := User{
Name: "John",
Age: 30,
}
// YAMLエンコーダーを使って、ユーザー情報をYAML形式でファイルに書き込む
if err := yaml.NewEncoder(file).Encode(user); err != nil {
log.Fatal(err)
}
}
CSV
inputファイル
input.csv
Name,Age
John,30
読み込みサンプルコード
main.go
package main
import (
"encoding/csv" // CSVデコード用パッケージ
"fmt" // フォーマット済み入出力用パッケージ
"log" // ログ出力用パッケージ
"os" // ファイル操作用パッケージ
"strconv" // 文字列⇔数値変換用パッケージ
)
// User構造体はCSVデータのユーザー情報を表現します
type User struct {
Name string
Age int
}
const filePath = "input.csv" // 読み込むCSVファイルのパス
func main() {
// 読み込み専用でCSVファイルをオープン
file, err := os.Open(filePath)
if err != nil {
log.Fatal(err)
}
defer file.Close()
reader := csv.NewReader(file)
records, err := reader.ReadAll()
if err != nil {
log.Fatal(err)
}
// ヘッダー行を除き、2行目のレコードをUser構造体に変換(例として)
if len(records) < 2 {
log.Fatal("レコードが不足しています")
}
age, err := strconv.Atoi(records[1][1])
if err != nil {
log.Fatal(err)
}
user := User{
Name: records[1][0],
Age: age,
}
// 読み込んだユーザー情報を出力
fmt.Printf("%+v\n", user) // {Name:John Age:30}
}
書き込みサンプルコード
main.go
package main
import (
"encoding/csv" // CSVエンコード用パッケージ
"log" // ログ出力用パッケージ
"os" // ファイル操作用パッケージ
"strconv" // 数値を文字列に変換するためのパッケージ
)
// User構造体はユーザー情報を保持します
type User struct {
Name string
Age int
}
const filePath = "output.csv" // 書き込み先のCSVファイルパス
func main() {
// 書き込み可能な状態でCSVファイルをオープン(存在しなければ作成、存在すれば上書き)
file, err := os.OpenFile(filePath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
if err != nil {
log.Fatal(err)
}
defer file.Close()
writer := csv.NewWriter(file)
defer writer.Flush()
// ヘッダー行の書き込み
if err := writer.Write([]string{"Name", "Age"}); err != nil {
log.Fatal(err)
}
user := User{
Name: "John",
Age: 30,
}
// ユーザー情報の書き込み
record := []string{user.Name, strconv.Itoa(user.Age)}
if err := writer.Write(record); err != nil {
log.Fatal(err)
}
}
txt
inputファイル
input.txt
John
30
読み込みサンプルコード
main.go
package main
import (
"bufio" // バッファ付き入出力用パッケージ
"fmt" // フォーマット済み入出力用パッケージ
"log" // ログ出力用パッケージ
"os" // ファイル操作用パッケージ
"strconv" // 文字列⇔数値変換用パッケージ
)
const filePath = "input.txt" // 読み込むテキストファイルのパス
func main() {
// 読み込み専用でテキストファイルをオープン
file, err := os.Open(filePath)
if err != nil {
log.Fatal(err)
}
defer file.Close()
scanner := bufio.NewScanner(file)
var lines []string
// 1行ずつ読み込み
for scanner.Scan() {
lines = append(lines, scanner.Text())
}
if err := scanner.Err(); err != nil {
log.Fatal(err)
}
// 入力ファイルは2行あることを想定(1行目: Name、2行目: Age)
if len(lines) < 2 {
log.Fatal("入力ファイルの行数が不足しています")
}
name := lines[0]
age, err := strconv.Atoi(lines[1])
if err != nil {
log.Fatal(err)
}
// 読み込んだユーザー情報を出力
fmt.Printf("{Name:%s, Age:%d}\n", name, age) // {Name:John, Age:30}
}
書き込みサンプルコード
main.go
package main
import (
"bufio" // バッファ付き入出力用パッケージ
"log" // ログ出力用パッケージ
"os" // ファイル操作用パッケージ
)
const filePath = "output.txt" // 書き込み先のテキストファイルパス
func main() {
// 書き込み可能な状態でテキストファイルをオープン(存在しなければ作成、存在すれば上書き)
file, err := os.OpenFile(filePath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
if err != nil {
log.Fatal(err)
}
defer file.Close()
writer := bufio.NewWriter(file)
// ユーザー情報 "John" と "30" を1行ずつ書き込む
if _, err := writer.WriteString("John\n"); err != nil {
log.Fatal(err)
}
if _, err := writer.WriteString("30\n"); err != nil {
log.Fatal(err)
}
writer.Flush()
}
Excel
inputファイル
input.xlsx
Name | Age |
---|---|
John | 30 |
このテーブルは、シート "Sheet1" の以下のセルに対応します:
-
セル A1:
Name
-
セル B1:
Age
-
セル A2:
John
-
セル B2:
30
読み込みサンプルコード
main.go
package main
import (
"fmt" // フォーマット済み入出力用パッケージ
"log" // ログ出力用パッケージ
"strconv" // 文字列⇔数値変換用パッケージ
"github.com/xuri/excelize/v2" // Excel操作用パッケージ
)
const filePath = "input.xlsx" // 読み込むExcelファイルのパス
func main() {
f, err := excelize.OpenFile(filePath)
if err != nil {
log.Fatal(err)
}
// シート "Sheet1" のセルから値を取得
name, err := f.GetCellValue("Sheet1", "A2")
if err != nil {
log.Fatal(err)
}
ageStr, err := f.GetCellValue("Sheet1", "B2")
if err != nil {
log.Fatal(err)
}
age, err := strconv.Atoi(ageStr)
if err != nil {
log.Fatal(err)
}
fmt.Printf("{Name:%s, Age:%d}\n", name, age) // {Name:John, Age:30}
}
書き込みサンプルコード
main.go
package main
import (
"log" // ログ出力用パッケージ
"github.com/xuri/excelize/v2" // Excel操作用パッケージ
)
const filePath = "output.xlsx" // 書き込み先のExcelファイルパス
func main() {
f := excelize.NewFile()
// 新しいシート "Sheet1" を作成
sheetName := "Sheet1"
index := f.NewSheet(sheetName)
// ヘッダーの書き込み
f.SetCellValue(sheetName, "A1", "Name")
f.SetCellValue(sheetName, "B1", "Age")
// ユーザー情報の書き込み
f.SetCellValue(sheetName, "A2", "John")
f.SetCellValue(sheetName, "B2", 30)
// アクティブなシートを設定
f.SetActiveSheet(index)
// Excelファイルを保存
if err := f.SaveAs(filePath); err != nil {
log.Fatal(err)
}
}
ini
inputファイル
input.ini
[User]
Name = John
Age = 30
読み込みサンプルコード
main.go
package main
import (
"fmt" // フォーマット済み入出力用パッケージ
"log" // ログ出力用パッケージ
"gopkg.in/ini.v1" // INIファイル操作用パッケージ
)
const filePath = "input.ini" // 読み込むINIファイルのパス
func main() {
cfg, err := ini.Load(filePath)
if err != nil {
log.Fatal(err)
}
name := cfg.Section("User").Key("Name").String()
age, err := cfg.Section("User").Key("Age").Int()
if err != nil {
log.Fatal(err)
}
fmt.Printf("{Name:%s, Age:%d}\n", name, age)
}
書き込みサンプルコード
main.go
package main
import (
"log" // ログ出力用パッケージ
"gopkg.in/ini.v1" // INIファイル操作用パッケージ
)
const filePath = "output.ini" // 書き込み先のINIファイルパス
func main() {
cfg := ini.Empty()
sec, err := cfg.NewSection("User")
if err != nil {
log.Fatal(err)
}
sec.NewKey("Name", "John")
sec.NewKey("Age", "30")
if err := cfg.SaveTo(filePath); err != nil {
log.Fatal(err)
}
}
XML
inputファイル
input.xml
<?xml version="1.0" encoding="UTF-8"?>
<User>
<Name>John</Name>
<Age>30</Age>
</User>
読み込みサンプルコード
main.go
package main
import (
"encoding/xml" // XMLエンコード/デコード用パッケージ
"fmt" // フォーマット済み入出力用パッケージ
"log" // ログ出力用パッケージ
"os" // ファイル操作用パッケージ
)
// User構造体はXMLデータのユーザー情報を表現します
type User struct {
XMLName xml.Name `xml:"User"`
Name string `xml:"Name"`
Age int `xml:"Age"`
}
const filePath = "input.xml" // 読み込むXMLファイルのパス
func main() {
// 読み込み専用でXMLファイルをオープン
file, err := os.Open(filePath)
if err != nil {
log.Fatal(err)
}
defer file.Close()
var user User
// XMLデコーダーでファイルの内容をUser構造体にデコード
if err := xml.NewDecoder(file).Decode(&user); err != nil {
log.Fatal(err)
}
// デコードしたユーザー情報を出力
fmt.Printf("%+v\n", user) // {XMLName:{Space: Local:User} Name:John Age:30}
}
書き込みサンプルコード
main.go
package main
import (
"encoding/xml" // XMLエンコード/デコード用パッケージ
"log" // ログ出力用パッケージ
"os" // ファイル操作用パッケージ
)
// User構造体はユーザー情報を保持します
type User struct {
XMLName xml.Name `xml:"User"`
Name string `xml:"Name"`
Age int `xml:"Age"`
}
const filePath = "output.xml" // 書き込み先のXMLファイルパス
func main() {
// 書き込み可能な状態でXMLファイルをオープン(存在しなければ作成、存在すれば上書き)
file, err := os.OpenFile(filePath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
if err != nil {
log.Fatal(err)
}
defer file.Close()
user := User{
Name: "John",
Age: 30,
}
encoder := xml.NewEncoder(file)
encoder.Indent("", " ")
if err := encoder.Encode(user); err != nil {
log.Fatal(err)
}
}
まとめ
今回の記事では、Go言語を用いた各種ファイルフォーマットの読み込みと書き込みのサンプルコードを紹介しました。JSON、YAML、CSV、TXT、EXCEL、INI、XMLと多岐にわたるファイル形式に対応するコード例は、現場で頻繁にファイル操作を行う私自身の経験に基づいており、実務ですぐに活用できる内容となっています。各サンプルコードは公式パッケージの仕様に準拠しているため、初学者から実務者まで参考にしていただければ幸いです。