---
# System prepended metadata

title: 第一次創建 Gin 網站就卡住

---

# 第一次創建 Gin 網站就卡住

這是我第一次利用極度不熟的 GO 語法搭建網站後台，依照直覺當然是先找一個最多人用的後台框架來實驗。網路上對於 GO 來說很多人都會推薦 GIN 來當做後台框架的首選，因此我就找了 GIN 框架來實作一下。

## 安裝 Gin 套件
實作前還是要先記錄一下 Gin 的安裝

### 下載 Gin 套件
```
$ go get -u github.com/gin-gonic/gin
```
*需符合 go 最小版本 v1.11*

### 測試 Gin 套件
```
package main

import "github.com/gin-gonic/gin"

func main() {
	r := gin.Default()
	r.GET("/ping", func(c *gin.Context) {
		c.JSON(200, gin.H{
			"message": "pong",
		})
	})
	r.Run() // listen and serve on 0.0.0.0:8080 (for windows "localhost:8080")
}
```
### 執行 gin 服務
```
go run example.go
```
### 開瀏覽器測試
```
localhost:8080/ping
```

-----


## 教學範例
[Building Go Web Applications and Microservices Using Gin](https://semaphoreci.com/community/tutorials/building-go-web-applications-and-microservices-using-gin)

## 實作
依照上面那個連結來實作一個簡單的 GIN 框架，包含幾個頁面與 Endpoint，最後的成果放在[這裡](https://github.com/Jemmy1234/go_web/tree/master/gin_example)。

我沒有實作最後面的 利用 Semaphore 整合 Github 來做 CI/CD 的部份，因為我覺得實際上在公司內的專案大部份的程式大概不會放在 Github 上，而且以公司內的專案來說，可能會架設自用的 Jenkins 或甚至利用公司內部的 Gitlab 來跑 Runner 以實行 CI / CD，因此我就先跳過 Semaphore 的部份。

因此我這次實作的內容包括:
1. 安裝 GOLANG / Gin
2. 設定好 Visual Code 的 Go 環境
3. 創建最簡單且可以接受 Request 的 Gin 框架
4. 加上 templates 資料夾，並在 templates 資料夾中開始加入許多組合頁面
5. 讓 Gin 可以讀取 templates 資料夾中的頁面
6. 讓 Gin 可以依照不同 Request 指定到不同的 Endpoint ，且呈現相對應的網頁頁面
7. 創建虛擬網頁資料，原本應該是要從資料庫讀取，這裡為了方便起見會先用 struct 寫死在一個程式檔案中
8. Gin 網頁資料可以動態的讀取上述的資料集並呈現在網頁中
9. 根據 Request 的標頭來判斷需回應的型式，包括最簡單的網頁，Json 以及 XML
10. 撰寫測試程式，且可以一次執行所有的測試程式

## 詭異的表情=.=
1. 一開始在考慮到底是在 Windows 安裝還是在 Ubuntu 系統中安裝，我一開始是覺得在 Ubuntu  安裝要裝什麼都自己來應該是 OK，但是後來遇到一個狀況是我要安裝 Gin 套件時，我的 GOLANG 版本過舊，必須從 10 升到 11 ，光這個部份，我花了很多時間去找方法解安裝 v10 ，重新安裝 v11 ，再設定 GoLANG 的 PATH，因為 v10 和 v11 有一些 path 預設不一樣，最後才安裝 Gin 套件。現在想想如果是在 Windows 架構下，因為是使用 Chocolatey 來幫忙安裝 GOLANG，所以就算要重新安裝或更新新版，這些環境變數應該不用自己設定，可能會方便許多。
2. Visual Code 的 Go 套件 **就是微軟出品的那個** 真的很方便，幾乎裝完了這個套件後，其他不足的套件它會自動提示你，所以就照著它說的繼續裝完就好了，不用擔心自己什麼沒裝，真的很可以。
3. GOLANG 有內建單元測試套件，可以非常快速的針對所寫的程式做測試，這就是為什麼這個教學裡有那麼多 xxx_test.go 的檔案，我之後會針對這個部份再多做幾個小練習。
4. 就這個練習來看，我覺得利用 GOLANG 搭配 Gin 架設一個後端平台真的是蠻快速的，幾乎在架設網站一開始會遇到的問題他都有快速的解決方法，例如簡潔的製作多個入口，跟網頁搭配呈現方式，甚至快速符合不同需求吐回資料等等。
5. 目前對我來說最大的問題反而是 GO 語言的掌握度不足，雖然我很高興我又從半直譯式語言 (Python) 跳回到編譯式語言，但是 GO 的習慣又不符合 OOP 的架構，更不用說又把我極度討厭的 C 程式裡的指標給搬出來了，雖然說 GO 這邊對於指標的使用是大大的減化了，但是看起來練習的路還有一段要走。

## GOLANG 新手就是會碰到的腦殘問題
1. struct 問題
```
type article struct {
  ID      int    json:"id"
  Title   string json:"title"
  Content string json:"content"
}
```
在 *models.article.go* 那個部份的程式有出現上面這個struct，我一直編譯不過，然後才知道它打錯了，正確的應該是
```
＃　正確寫法
type article struct {
  ID      int    `json:"id"`
  Title   string `json:"title"`
  Content string `json:"content"`
}
```
有發現不一樣的地方了嗎? 正確的會在每一行的最後面的前後加上那個小點點，上網查了才知道原來這是 GOLANG 的語法之一，而且那個鍵是利用鍵盤上的 1 的左邊那個按鍵，有很多人會把它按成是 Enter 左邊那個按鍵。基本上在 struct 裡有一個語法叫做 **TAG** 的語法，就是放在 struct 最後面的 **‵json:"id"‵** 這一串，需要用1左邊那個按鍵去把它給括起來。裡面是一個 key-value 的組合，前面的 key 是一個已經定義好的部份，by golang ，例如 json 就是它已經定義好的，它的作用是直接可以幫你把這個欄位當碰到特殊的狀況，例如 json 格式時，直接轉換成你 tag 裡所定義好的 value。

2. 大括號問題
```
func initializeRoutes() {
    router.GET("/", showIndexPage)
}
```
我一開始會把第一行的括號往下放，例如
```
func initializeRoutes()
{
    router.GET("/", showIndexPage)
}
```
在很多其他的程式語言，例如 Java ，這樣的寫法沒什麼特別的，但是偏偏在 GOLANG 裡，這樣是編譯不過的，原因是因為，GO 編譯器其實會主動在特定的字元後面做分段，也就是加上  **;** ，因此如果是我自己寫法的話，就會變成
```
func initializeRoutes();
{
    router.GET("/", showIndexPage)
}
```
很明顯的這會有問題對吧，所以在 GOLANG 裡，func 後面的大括號請不要主動移到下一行，謝謝。