Open10

goの学習

mookmook

Goの学習用のスクラップです。
よく使う処理をコメントとして残します。

mookmook

標準出力の書き込みを削除する。

package main

import (
	"fmt"
	"strings"
	"time"
)

func main() {
	fmt.Print("書き込み中です")
	time.Sleep(3 * time.Second)
	fmt.Print("\r" + strings.Repeat(" ", 10) + "\r")
}

mookmook

自動で消えるプログレスバー

package utils

import (
	"fmt"
	"strings"
)

type ProgressBar struct {
	Total      int
	Count    int
	BarWidth   int
}

func (pb *ProgressBar) Write() {

	// 進捗率を計算
	ratio := float64(pb.Count) / float64(pb.Total)
	blocks := int(ratio * float64(pb.BarWidth))

	// 棒グラフを作成
	bar := fmt.Sprintf("\r[%s%s] %3.0f%%",
		strings.Repeat("#", blocks),
		strings.Repeat("-", pb.BarWidth-blocks),
		ratio*100,
	)

	// 上書を表示
	fmt.Print(bar)
}

func (pb *ProgressBar) Delete() {
	fmt.Print("\r" + strings.Repeat(" ", pb.BarWidth+10) + "\r")
}

func main() {
	// プログレスバーを初期化
	progressbar := &utils.ProgressBar{Total: 100, Count: 0, BarWidth: 40}

	for i := 0; i < 100; i++ {
		time.Sleep(1 * time.Second)
		progressbar.Count = i
		progressbar.Write()
	}
}
mookmook

指定されたファイルをダウンロードする(例は画像ファイルのダウンロード用)

package utils

import (
	"fmt"
	"io"
	"net/http"
	"os"
)

func GetImg(imgURL string, path string, fileName string) {
	// HTTP GETリクエストで画像データを取得
	resp, err := http.Get(imgURL)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()

	// 保存用ファイルを作成
	out, err := os.Create(fmt.Sprintf("%s/%d.jpg", path, fileName))
	if err != nil {
		panic(err)
	}
	defer out.Close()

	// 画像データをファイルにコピー
	_, err = io.Copy(out, resp.Body)
	if err != nil {
		panic(err)
	}
}
mookmook

ファイル・フォルダ関連

mookmook

ファイルが存在するかのチェック

func fileExists(dir, filename string) bool {
    path := filepath.Join(dir, filename)
    info, err := os.Stat(path)
    if err != nil {
        return false // エラーがある = 存在しない(またはアクセス不可)
    }
    return !info.IsDir() // ディレクトリではなくファイルなら true
}
mookmook

フォルダを作成する

  • os.Mkdir:フォルダを作成する
  • os.MkdirAll: フォルダを再帰的に作成する

Mkdirは、指定された名前とパーミッション(umaskの前)で新しいディレクトリを作成する。ビット(umaskの前)。エラーが発生した場合、型は *PathError となる。

MkdirAll は path という名前のディレクトリを作成する、必要な親も一緒に作成し、nil を返す、またはエラーを返す。MkdirAll が作成するディレクトリには、perm (umask の前) というパーミッションビットが使用されます。MkdirAll が作成するすべてのディレクトリに使用される。
path がすでにディレクトリである場合、MkdirAll は何もしない。nil を返す。

フォルダ・ファイルの削除

  • os.Remove: 指定されたファイルまたは空ディレクトリを削除する。
  • os.RemoveAll: パスとパスの子ファイルや子ディレクトリを含めて削除する。

Remove は指定されたファイルまたはディレクトリを削除する。エラーが発生した場合は、*PathError型になります。

RemoveAll はパスと、それが含むすべての子を削除する。可能な限りすべてを削除しますが、最初に遭遇したエラーを返します。を返します。 パスが存在しない場合、RemoveAllはnil(エラーなし)を返します。エラーがある場合、それは [*PathError] 型になります。

import os

func main() {
    os.Mkdir("path", "0755")
    os.MkdirAll("path", "0755")
    os.Remove("path")
    os.RemoveAll("path")
}
mookmook

ファイル・ディレクトリの名称変更

Renameはoldpathをnewpathにリネーム(移動)する。newpathがすでに存在し、ディレクトリでない場合、Renameはそれを置き換える。newpathがすでに存在し、ディレクトリである場合、Renameはエラーを返す。oldpathとnewpathが異なるディレクトリにある場合、OS固有の制限が適用されることがある。同じディレクトリ内であっても、Unix以外のプラットフォームでは、 Renameはアトミックな操作ではない。エラーが発生した場合、それは *LinkError 型である。

package main

import (
	"fmt"
	"os"
)

func main() {
	err := os.Rename("aaa.txt", "bbb.txt")
	if err != nil {
		fmt.Printf("Error: %s\n", err)
	}
}
mookmook

ディレクトリ内の各ファイルを走査する

対象のディレクトリのツリー構造

tree
aaa
├── 1111
├── 2222
├── 3333
└── bbbb
    ├── 1111
    ├── 2222
    └── ccccc
        ├── 1111
        └── 2222

プログラム実行後の出力

Output
0: aaa
1: aaa/1111
2: aaa/2222
3: aaa/3333
4: aaa/bbbb
5: aaa/bbbb/1111
6: aaa/bbbb/2222
7: aaa/bbbb/ccccc
8: aaa/bbbb/ccccc/1111
9: aaa/bbbb/ccccc/2222

プログラム

package main

import (
	"fmt"
	"os"
	"path/filepath"
)

func main() {
	// func filepath.Walk(root string, fn filepath.WalkFunc) error
	// type WalkFunc func(path string, info fs.FileInfo, err error) error
	dirPath := "aaa"
	var pathList []string
	err := filepath.Walk(dirPath, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			// どんなエラーが発生する可能性がある?
			// - 実行中に別のプロセスでファイルやディレクトリが削除された
			// - 読み取り権限のないファイル等へのアクセス
			//   権限のないファイルへのアクセス時にエラーが発生する
			fmt.Println("エラー:", err)
			return filepath.SkipDir
		}

		if info.IsDir() {
			// ディレクトリです
		}
		pathList = append(pathList, path)
		return nil
	})

	if err != nil {
		fmt.Println("Walkエラー: %w", err)
	} else {
		for i, v := range pathList {
			fmt.Printf("%00d: %s\n", i, v)
		}
	}

}