iT邦幫忙

2023 iThome 鐵人賽

DAY 15
0
Software Development

Go朱尼爾的學習雜記系列 第 17

0x17 Go HTTP Server Basic

  • 分享至 

  • xImage
  •  

今天接著介紹 Golang 非常強大的 std lib: HTTP

我們直接上 code

  1. hello http
package main

import (
	"fmt"
	"net/http"
)

const port = ":8887"

func main() {

  // 定義了路由, 然後處理函式
	http.HandleFunc("/hello", Hello)

  // 先印個提示訊息
	fmt.Println("listening: " + port)
	// 監聽 port :8887, 第二個參數可以自訂更詳細的 http 處理函式, 為了簡化先不詳述
  http.ListenAndServe(port, nil)
}

func Hello(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintln(w, "hello world")
}

可以打開 curl curl localhost:8887/hello, 做個簡單測試, go 要起個簡單的 http server 就是如此容易

以上小試身手一下, 接著我們實務一點的情況去處理

  1. basic http
package main

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
)

const port = ":8887"

func main() {

	// 這邊我們改模擬個 login api
	http.HandleFunc("/login", Login)

	// 示範怎麼快速把靜態檔案提供出去
	http.Handle("/", http.FileServer(http.Dir("public")))

	fmt.Println("listening: " + port)
	// 這邊做個錯誤捕捉, 有時候自己port被佔到不自知, 有錯誤訊息就比較省時間
	err := http.ListenAndServe(port, nil)
	if err != nil {
		log.Fatal(err)
	}
}

// 習慣上會先用個 struct 起來接資料
type userParam struct {
	Email    string `json:"email"`
	Password string `json:"password"`
}

func Login(w http.ResponseWriter, r *http.Request) {

	// 由於內建沒有捕捉 method, 我們自己寫
	if r.Method != "POST" {
		w.WriteHeader(http.StatusBadRequest)
		fmt.Fprintf(w, "method not allowed")
		return
	}

	// 這邊開始解析 body資料, 個人是滿喜歡 json decode/encode 這種方式
	user := userParam{}
	err := json.NewDecoder(r.Body).Decode(&user)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		fmt.Fprintf(w, "data error, please try again")
		return
	}
	// 這邊 log 出來看, 資料實際有接收到
	fmt.Printf("%+v", user)

	// 這邊設定個 headers
	w.Header().Set("Content-Type", "application/json")
	// 這邊把 w 拿去做 encoder, 資料就會直接出去了
	err = json.NewEncoder(w).Encode(user)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		fmt.Fprintf(w, "json encode failed")
		return
	}

}

第二種我們做了更多示範, 有提供靜態檔案, 有把 post body 資料擷取下來, 並且用 json 回傳, 寫起來舒服因為不用依賴太多東西, 但寫久了還是想偷懶怎辦, 請參考第三種

  1. fiber http
package main

import (
	"fmt"
	"log"

	"github.com/gofiber/fiber/v2"
	"github.com/gofiber/fiber/v2/middleware/cors"
	"github.com/gofiber/fiber/v2/middleware/logger"
	"github.com/gofiber/fiber/v2/middleware/recover"
)

func main() {
	app := fiber.New()

  // 封裝好的各式中間件, 我們就不需要自己寫了! 
	app.Use(cors.New())    // cors allow *
	app.Use(logger.New())  // logger middleware
	app.Use(recover.New()) // recover middleware

  // 最大的好處, 直接 serve 出來就是 SPA 了, 方便!
	app.Static("/", "public")

	app.Get("/hello", Hello)

  // 有 method 分類可以用了!
	app.Post("/login", Login)

	if err := app.Listen(":8887"); err != nil {
		log.Fatal(err)
	}
}

func Hello(c *fiber.Ctx) error {
	return c.SendString("Hello, World 👋!")
}

type userParam struct {
	Email    string `json:"email"`
	Password string `json:"password"`
}

func Login(c *fiber.Ctx) error {
	user := &userParam{}
  // body parser 也是簡簡單單
	err := c.BodyParser(user)
	if err != nil {
		return c.Status(422).SendString("data error")
	}

	fmt.Printf("%+v", user)

  // 很舒服的就送回去了
	return c.JSON(user)
}

推薦進階閱讀:
7天用Go从零实现Web框架Gee教程


上一篇
0x16 React useContext 跟 redux
下一篇
0x18 JWT Token Backend
系列文
Go朱尼爾的學習雜記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言