Go　備忘録

:::note
あくまで個人向けの備忘録として書いていることをご承知おきください
:::

### 開発の一番はじめに行うこと
※`example.com/hello`にgitリポジトリを置く前提
もし、他のプログラムからmoduleとして呼ばない場合、適当にhelloなどでも良い。
```bash
go mod init example.com/hello
```



### HTTPハンドラー（一部）
```go
    // 最初の値(p)にキー"page"の下に保存された値が割り当てられる
	// そのキーが存在しない場合、pは値型のゼロ値(0)になる。
	// 2番目の値(ok)は、キーがマップに存在する場合はtrue、存在しない場合はfalseのbool型の値が入る。
	if p, ok := queryMap["page"]; ok && len(p) > 0 {
		var err error
		page, err = strconv.Atoi(p[0])

		if err != nil {
			http.Error(w, "Invalid query parameter", http.StatusBadRequest)
			return
		}
	} else {
		page = 1
	}
```

### フォーマット指定子
#### `%v`
- 汎用のフォーマット指定子
- 構造体の場合、値が表示される
    ```go
    package main

    import (
    	"fmt"
    )

    type User struct {
    	ID   int
    	Name string
    	Age  int
    }

    func main() {
    	user1 := User{
    		ID:   123,
    		Name: "Sam",
    		Age:  25,
    	}
    	fmt.Printf("%v\n", user1)
    }
    ```
    ```bash
    # 出力結果
    {123 Sam 25}
    ```

#### `%+v`
- 構造体の場合、フィールド・値が表示される
    ```go
    package main

    import (
    	"fmt"
    )

    type User struct {
    	ID   int
    	Name string
    	Age  int
    }

    func main() {
    	user1 := User{
    		ID:   123,
    		Name: "Sam",
    		Age:  25,
    	}
    	fmt.Printf("%+v\n", user1) // ココが「%+v」
    }
    ```
    ```bash
    # 出力結果
    {ID:123 Name:Sam Age:25}
    ```

#### `%#v`
- 構造体の場合、型・フィールド・値が表示される
    ```go
    package main

    import (
    	"fmt"
    )

    type User struct {
    	ID   int
    	Name string
    	Age  int
    }

    func main() {
    	user1 := User{
    		ID:   123,
    		Name: "Sam",
    		Age:  25,
    	}
    	fmt.Printf("%#v\n", user1) // ココが「%#v」
    }
    ```
    ```bash
    # 出力結果
    main.User{ID:123, Name:"Sam", Age:25}
    ```

### Go構造体→JSONにエンコード
- JSONへのエンコードには`json.Marshal`関数を用いる
    ```go
        package main

        import (
        	"encoding/json"
        	"fmt"
        	"time"
        )

        type Comment struct {
        	CommentID int       `json:"comment_id"`//タグ（jsonキーの名前を指定）
        	ArticleID int       `json:"article_id"`
        	Message   string    `json:"message"`
        	CreatedAt time.Time `json:"created_at""` // 標準パッケージtimeに含まれるtime.Time型
        }

        type Article struct {
        	ID          int       `json:""`
        	Title       string    `json:"title"`
        	Contents    string    `json:"contents"`
        	UserName    string    `json:"user_name"`
        	NiceNum     int       `json:"nice"`
        	CommentList []Comment `json:"comments"`
        	CreatedAt   time.Time `json:"created_at"`
        }

        func main() {
        	comment1 := Comment{
        		CommentID: 1,
        		ArticleID: 1,
        		Message:   "test comment1",
        		CreatedAt: time.Now(),
        	}
        	comment2 := Comment{
        		CommentID: 2,
        		ArticleID: 1,
        		Message:   "second comment1",
        		CreatedAt: time.Now(),
        	}
        	article := Article{
        		ID:          1,
        		Title:       "first article",
        		Contents:    "This is the test article.",
        		UserName:    "latte",
        		NiceNum:     1,
        		CommentList: []Comment{comment1, comment2},
        		CreatedAt:   time.Now(),
        	}

        	// fmt.Printf("%+v\n", article)
        	jsonData, err := json.Marshal(article)
        	if err != nil {
        		fmt.Println(err)
        		return
        	}

        	fmt.Printf("%s\n", jsonData)
        }
    ```

    ```bash
    // 出力結果（可読性のため改行を手入力）
    {
        "ID":1,
        "title":"first article",
        "contents":"This is the test article.",
        "user_name":"latte",
        "nice":1,
        "comments":[
            {
                "comment_id":1,
                "article_id":1,
                "message":"test comment1",
                "created_at":"2025-04-03T07:53:38.629926+09:00"
            },
            {
                "comment_id":2,
                "article_id":1,
                "message":"second comment1",
                "created_at":"2025-04-03T07:53:38.629926+09:00"
            }
        ],
        "created_at":"2025-04-03T07:53:38.629926+09:00"
    }
    ```