🕌
Goの標準パッケージについてメモを残していく
os
基本的なio、環境変数、パス、ファイル情報、プロセス関連などめちゃめちゃある
-
ファイル系
os.File型はio.ReadWriterインターフェースを満たす
// 開く
file1, _ := os.Open("test.txt")
io.WriteString(file1, "hello")
// 作成
file2, _ := os.Create("new.txt")
// 読み書き
// O_RDWR: 読み書き両方可能
// O_CREATE: ファイルが存在しない場合は作成
// O_TRUNC: ファイルが存在する場合は内容を切り詰める
file3, _ := os.OpenFile("test.txt", os.O_RDWR|os.O_CREATE|O_TRUNC, 0666)
// 削除
_ := os.Remove(file2)
// ディレクトリ作成
_ := os.Mkdir("dir", 0755) // 現在の階層から作成
_ := os.MkdirAll("path/to/dir", 0755) // 親階層から作成
- 環境変数
os.Setenv("PORT", "8080") // 環境変数の設定(テストで主に使う)
port := os.Getenv("PORT") // 環境変数の取得
envAll := os.Environ() // 全環境変数を取得
- ファイル情報
info, _ := os.Stat("go.mod") // ファイル情報の取得
fmt.Println(info.Size()) // 5
fmt.Println(info.Mode()) // -rw-r--r--
fmt.Println(info.ModTime()) // 2024-11-30 20:44:57.831299121 +0900 JST
// ファイルが存在するかチェック
_, err := os.Stat("file.txt")
if os.IsNotExist(err) {
os.Exit(1)
}
- プロセス系
pid := os.Getpid() // プロセスIDの取得
ppid := os.Getppid() // 親プロセスIDの取得
// プログラムの終了
// チャネルへの通知で使ったり
os.Exit(0) // 正常終了
os.Exit(1) // エラー終了
io
読み書きを抽象化するパッケージ。
いろんなパッケージがioのインターフェースを満たして
効率的にio操作してる
- 超重要インターフェース
// io.Readerインターフェースを満たしていてよく使う型
// *os.File - ファイル
// *bytes.Reader - バイト列
// *strings.Reader - 文字列
// *bufio.Reader - バッファ付きリーダー
// http.Response.Body - HTTPレスポンス
type Reader interface {
Read(p []byte) (n int, err error)
}
// io.Writerインターフェースを満たしていてよく使う型
// *os.File - ファイル
// *bytes.Buffer - メモリバッファ
// *bufio.Writer - バッファ付きライター
// http.ResponseWriter - HTTPレスポンス
type Writer interface {
Write(p []byte) (n int, err error)
}
type ReadWriter interface {
Reader
Writer
}
type Closer interface {
Close() error
}
strings
文字列操作。○○から始まる、○○が含まれるなどのチェックや不要な文字の削除によく使う
s := "Hello, World"
if strings.Contains(s, "Hello") {} // ○○が含まれる true
if strings.HasPrefix(s, "He") {} // ○○から始まる true
if strings.HasSuffix(s, "rld") {} // ○○で終わる true
path := "/api/v1/users/"
path = strings.Trim(path, "/") // "api/v1/users"
text := " Hello Hello "
text1 := strings.TrimSpace(text) // 空白除去
text2 := strings.ToLower(text) // 小文字化
text3 := strings.ReplaceAll(text, " ", "_") // 空白をアンダースコアに
fmt.Println(text1, text12 text3)
// "HelloHello", " hello hello ", "_Hello_Hello_"
bytes
stringsのbyteスライス版、でも操作よりもバッファとして使うのが多い
// バッファとして使用
var buf bytes.Buffer
for i := 0; i < 5; i++ {
buf.WriteString("hello, ")
}
fmt.Println(buf.String()) // hello, hello, hello, hello, hello,
// http.NewRequestのBodyに使用
person := struct {
Name string `json:"name"`
}{
Name: "John Doe",
}
jsonPayload, _ := json.Marshal(person)
req, _ := http.NewRequest("POST", "http://api.sample", bytes.NewBuffer(jsonPayload))
time
jst := time.LoadLocation("Asia/Tokyo") // タイムゾーン設定
t := time.Now().In(jst) // 現在時刻を取得(In関数はオプション)
now := t.Format("2006年01月02日 (Mon) 15:04:05") // 2024年11月30日 (Sat) 22:55:13
rfc := t.Format(time.RFC3339) // "2024-11-30T15:04:05Z08:00"
t.Add(24 * time.Hour) // 1日後
t.Add(0, -1, 0) // 1ヶ月前
t.Unix() // Unix時間(秒)
t.UnixNano() // Unix時間(ナノ秒)
errors
- カスタムエラー型
func Error() string
を満たすだけでerror型として扱える
type error interface {
Error() string
}
type FileError struct {
path string
}
func (e *FileError) Error() string {
return fmt.Errorf("ファイルが見つかりません: %w", e.path)
}
- エラーの作成、エラーの判定
func OpenFile(p string) (*os.File, error) {
f, err := os.Open(p)
if err != nil {
if errors.Is(os.IsNotExist) {
return nil, errors.New("ファイルが見つかりません。")
}
return nil, fmt.Errorf("予期せぬエラー: %w", err)
}
return f, nil
}
strconv
文字列と他のデータ型(例えば、数値)との間の変換
num, _ := strconv.Atoi("1") // 1
str = strconv.Itoa(1) // "1"
net/http
主にクライアント側
http.Get
func http.Get(url string) (resp *http.Response, err error)
シンプルなGETリクエスト
resp, _ := http.Get("http://api.sample")
defer resp.Body.Close()
b, _ := io.ReadAll(resp.Body) // *http.Responseを[]byteに変換
fmt.Println(string(b))
http.NewReqest
func http.NewRequest(method string, url string, body io.Reader) (*http.Request, error)
http.Requestでメソッド・URL・ボディをセットしてhttp.Clientからリクエスト
req, _ := http.NewRequest("GET", "http://api.sample", nil)
req.Header.Set("Authorization", "Bearer hoge")
client := http.Client{} // クライアント初期化
resp, _ := client.Do(req) // リクエストを送信
// func (c *http.Client) Do(req *http.Request) (*http.Response, error)
defer resp.Body.Close()
b, _ := io.ReadAll(resp.Body)
fmt.Println(string(b))
encoding/json
よく忘れる
json.NewDecoder
func json.NewDecoder(r io.Reader) *json.Decoder
io.Reader型をデコード。
resp, _ := http.Get("http://api.sample")
defer resp.Body.Close()
var person struct {
Name string `json:"name"`
}
if err := json.NewDecoder(resp.Body).Decode(&person); err != nil {
panic(err)
}
fmt.Println(person)
json.Unmarshal
func json.Unmarshal(data []byte, v any) error
[]byte型をデコード。
jsonStr := `{"name": "John"}`
var person struct {
Name string `json:"name"`
}
if err := json.Unmarshal([]byte(jsonStr), &person); err != nil {
panic(err)
}
fmt.Println(person)
json.NewEncoder
func json.NewEncoder(w io.Writer) *json.Encoder
io.Writer型をエンコード。
person := `{"name": "John"}`
var body bytes.Buffer
if err := json.NewEncoder(&body).Encode(person); err != nil {
return err
}
fmt.Println(body.String()) // "{\"name\": \"John\"}"
json.Marshal
func json.Marshal(v any) ([]byte, error)
[]byteにエンコード。
person := struct {
Name string `json:"name"`
}{
Name: "John Doe",
}
jsonByte, _ := json.Marshal(person)
fmt.Println(string(jsonByte)) // {"name":"John Doe"}
math/rand
r := rand.New(rand.NewSource(time.Now().UnixNano()))
// スライスのシャッフル
slice := []int{1, 2, 3, 4, 5}
r.Shuffle(len(slice), func(i, j int) {
slice[i], slice[j] = slice[j], slice[i]
})
fmt.Println(slice) // [2 4 1 3 5]
fmt.Println(slice) // [4 3 1 5 2]
// スライスからランダムな要素を選択
slice2 := []string{"apple", "banana", "orange"}
randomItem := slice[r.Intn(len(slice2))]
fmt.Println(randomItem) // 2
fmt.Println(randomItem) // 0
Discussion