ในบทความก่อนหน้านี้ในชุดนี้ เราได้พูดคุยกันอย่างกว้างขวางเกี่ยวกับ Gonet/http
แพ็คเกจและวิธีการใช้สำหรับเว็บแอปพลิเคชันที่พร้อมสำหรับการผลิต เราเน้นที่ด้านการกำหนดเส้นทางและลักษณะเฉพาะอื่นๆ ของhttp.ServeMux
เป็นส่วนใหญ่ ชนิด
บทความนี้จะปิดการสนทนาใน ServeMux
โดยการสาธิตวิธีใช้งานฟังก์ชันมิดเดิลแวร์กับเราเตอร์เริ่มต้นและแนะนำแพ็คเกจไลบรารีมาตรฐานอื่นๆ ที่แน่ใจว่าจะมีประโยชน์เมื่อพัฒนาบริการเว็บด้วย Go
มิดเดิลแวร์ใน Go
วิธีปฏิบัติในการตั้งค่าฟังก์ชันที่ใช้ร่วมกันซึ่งต้องเรียกใช้สำหรับคำขอ HTTP แบบปากเปล่าจำนวนมากเรียกว่า มิดเดิลแวร์ . การดำเนินการบางอย่าง เช่น การตรวจสอบสิทธิ์ การบันทึก และการตรวจสอบคุกกี้ มักถูกนำไปใช้เป็นฟังก์ชันมิดเดิลแวร์ ซึ่งดำเนินการตามคำขออย่างเป็นอิสระก่อนหรือหลังตัวจัดการเส้นทางปกติ
ในการใช้งานมิดเดิลแวร์ใน Go คุณต้องแน่ใจว่าคุณมีประเภทที่ตรงกับอินเทอร์เฟซ http.Handler โดยปกติหมายความว่าคุณต้องแนบเมธอดที่มีลายเซ็นServeHTTP(http.ResponseWriter, *http.Request)
กับประเภท เมื่อใช้เมธอดนี้ ทุกประเภทจะตอบสนอง http.Handler
อินเทอร์เฟซ
นี่เป็นตัวอย่างง่ายๆ:
package main
import "net/http"
type helloHandler struct {
name string
}
func (h helloHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Hello " + h.name))
}
func main() {
mux := http.NewServeMux()
helloJohn := helloHandler{name: "John"}
mux.Handle("/john", helloJohn)
http.ListenAndServe(":8080", mux)
}
คำขอใด ๆ ที่ส่งไปยัง /john
เส้นทางจะถูกส่งตรงไปยังhelloHandler.ServeHTTP
กระบวนการ. คุณสามารถสังเกตการทำงานนี้ได้โดยเริ่มต้นเซิร์ฟเวอร์และไปที่ https://localhost:8080/john
ต้องเพิ่ม ServeHTTP
เมธอดเป็นประเภทกำหนดเองทุกครั้งที่คุณต้องการปรับใช้ http.Handler
จะค่อนข้างน่าเบื่อ ดังนั้น net/http
packageprovides http.HandlerFunc
ซึ่งอนุญาตให้ใช้ฟังก์ชันทั่วไปเป็นตัวจัดการ HTTP
สิ่งที่คุณต้องทำคือตรวจสอบให้แน่ใจว่าฟังก์ชันของคุณมีลายเซ็นต่อไปนี้:func(http.ResponseWriter, *http.Request)
; จากนั้นแปลงเป็น http.HandlerFunc
ชนิด
package main
import "net/http"
func helloJohnHandler(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Hello John"))
}
func main() {
mux := http.NewServeMux()
mux.Handle("/john", http.HandlerFunc(helloJohnHandler))
http.ListenAndServe(":8080", mux)
}
คุณยังสามารถแทนที่ mux.Handle
บรรทัดใน main
ฟังก์ชั่นด้านบนด้วยmux.HandleFunc
และส่งฟังก์ชันไปที่มันโดยตรง เราใช้รูปแบบนี้โดยเฉพาะในบทความที่แล้ว
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/john", helloJohnHandler)
http.ListenAndServe(":8080", mux)
}
ณ จุดนี้ ชื่อถูกฮาร์ดโค้ดลงในสตริง ไม่เหมือนเมื่อก่อนเมื่อเราตั้งชื่อใน main
ก่อนเรียกตัวจัดการ หากต้องการลบข้อจำกัดนี้ เราสามารถปิดตรรกะของตัวจัดการได้ดังที่แสดงด้านล่าง:
package main
import "net/http"
func helloHandler(name string) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Hello " + name))
})
}
func main() {
mux := http.NewServeMux()
mux.Handle("/john", helloHandler("John"))
http.ListenAndServe(":8080", mux)
}
helloHandler
ฟังก์ชันเองไม่เป็นไปตาม http.Handler
ส่วนต่อประสาน แต่สร้างและส่งคืนฟังก์ชันที่ไม่ระบุชื่อที่ทำ ฟังก์ชันนี้ปิดทับ name
พารามิเตอร์ ซึ่งหมายความว่าสามารถเข้าถึงได้เมื่อถูกเรียก ณ จุดนี้ helloHandler
สามารถใช้ซ้ำได้หลายชื่อตามความจำเป็น
ทั้งหมดนี้เกี่ยวข้องกับมิดเดิลแวร์อย่างไร การสร้างฟังก์ชันมิดเดิลแวร์ทำได้ในลักษณะเดียวกับที่เราได้เห็นด้านบน แทนที่จะส่งสตริงไปยังส่วนปิด (ดังในตัวอย่าง) เราสามารถส่งตัวจัดการถัดไปในสายโซ่เป็นอาร์กิวเมนต์ได้
นี่คือรูปแบบที่สมบูรณ์:
func middleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Middleware logic goes here...
next.ServeHTTP(w, r)
})
}
middleware
ฟังก์ชันด้านบนยอมรับตัวจัดการและส่งคืนตัวจัดการ โปรดสังเกตว่าเราสามารถทำให้ฟังก์ชันที่ไม่ระบุตัวตนตอบสนอง http.Handler
ได้อย่างไร โดยการแคสต์ไปที่ http.HandlerFunc
พิมพ์. เมื่อสิ้นสุดฟังก์ชันนิรนาม การควบคุมจะถูกโอนไปยัง next
ตัวจัดการโดยเรียกใช้ServeHTTP()
กระบวนการ. หากคุณต้องการส่งค่าระหว่างตัวจัดการ เช่น ID ของผู้ใช้ที่ตรวจสอบสิทธิ์ คุณสามารถใช้ http.Request.Context()
วิธีการแนะนำใน Go 1.7
มาเขียนฟังก์ชันมิดเดิลแวร์ที่แสดงให้เห็นรูปแบบนี้ง่ายๆ กัน ฟังก์ชันนี้เพิ่มคุณสมบัติที่เรียกว่า requestTime
ไปยังออบเจกต์คำขอซึ่งใช้โดย helloHandler
เพื่อแสดงการประทับเวลาของคำขอ
package main
import (
"context"
"net/http"
"time"
)
func requestTime(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
ctx = context.WithValue(ctx, "requestTime", time.Now().Format(time.RFC3339))
r = r.WithContext(ctx)
next.ServeHTTP(w, r)
})
}
func helloHandler(name string) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
responseText := "<h1>Hello " + name + "</h1>"
if requestTime := r.Context().Value("requestTime"); requestTime != nil {
if str, ok := requestTime.(string); ok {
responseText = responseText + "\n<small>Generated at: " + str + "</small>"
}
}
w.Write([]byte(responseText))
})
}
func main() {
mux := http.NewServeMux()
mux.Handle("/john", requestTime(helloHandler("John")))
http.ListenAndServe(":8080", mux)
}
เนื่องจากฟังก์ชันมิดเดิลแวร์ของเรายอมรับและส่งกลับ http.Handler
พิมพ์ มันเป็นไปได้ที่จะสร้างห่วงโซ่ที่ไม่มีที่สิ้นสุดของฟังก์ชันมิดเดิลแวร์ที่ซ้อนกันอยู่ภายในกันและกัน
ตัวอย่างเช่น
mux := http.NewServeMux()
mux.Handle("/", middleware1(middleware2(appHandler)))
คุณสามารถใช้ห้องสมุดเช่น Alice เพื่อแปลงโครงสร้างด้านบนให้อยู่ในรูปแบบที่อ่านง่ายยิ่งขึ้น เช่น:
alice.New(middleware1, middleware2).Then(appHandler)
เทมเพลต
แม้ว่าการใช้เทมเพลตจะลดลงเมื่อมีแอปพลิเคชันหน้าเดียว แต่ยังคงเป็นส่วนสำคัญของโซลูชันการพัฒนาเว็บที่สมบูรณ์
Go มีแพ็คเกจสองชุดสำหรับทุกความต้องการในการสร้างแม่แบบของคุณ:text/template
และhtml/template
. ทั้งคู่มีอินเทอร์เฟซเดียวกัน แต่ส่วนหลังจะทำการเข้ารหัสลับเบื้องหลังเพื่อป้องกันการเจาะระบบโค้ดปลอม
แม้ว่าเทมเพลต Go จะไม่ได้สื่อถึงความรู้สึกได้มากที่สุด แต่ก็สามารถทำงานให้เสร็จลุล่วงได้ดีและสามารถใช้สำหรับแอปพลิเคชันที่ใช้งานจริงได้ อันที่จริงแล้ว Hugo ซึ่งเป็นเครื่องมือสร้างไซต์แบบสแตติกยอดนิยมนั้นใช้ระบบการสร้างเทมเพลตเป็นหลัก
เรามาดูกันว่า html/template
. เป็นอย่างไร แพ็กเกจอาจใช้เพื่อส่งเอาต์พุต HTML เพื่อตอบสนองต่อคำขอของเว็บ
การสร้างเทมเพลต
สร้าง index.html
ไฟล์ในไดเร็กทอรีเดียวกับ main.go
. ของคุณ file และเพิ่มรหัสต่อไปนี้ลงในไฟล์:
<ul>
{{ range .TodoItems }}
<li>{{ . }}</li>
{{ end }}
</ul>
ถัดไป เพิ่มรหัสต่อไปนี้ใน main.go
. ของคุณ ไฟล์:
package main
import (
"html/template"
"log"
"os"
)
func main() {
t, err := template.ParseFiles("index.html")
if err != nil {
log.Fatal(err)
}
todos := []string{"Watch TV", "Do homework", "Play games", "Read"}
err = t.Execute(os.Stdout, todos)
if err != nil {
log.Fatal(err)
}
}
หากคุณรันโปรแกรมด้านบนด้วย go run main.go
. คุณควรเห็นผลลัพธ์ต่อไปนี้:
<ul>
<li>Watch TV</li>
<li>Do homework</li>
<li>Play games</li>
<li>Read</li>
</ul>
ยินดีด้วย! คุณเพิ่งสร้างเทมเพลต Go แรกของคุณ นี่คือคำอธิบายสั้น ๆ ของไวยากรณ์ที่เราใช้ในไฟล์เทมเพลต:
- Go ใช้วงเล็บปีกกาคู่ (
{{
และ}}
) เพื่อกำหนดขอบเขตการประเมินข้อมูลและโครงสร้างการควบคุม (เรียกว่า การกระทำ ) ในเทมเพลต - ช่วง
range
การกระทำคือวิธีที่เราสามารถทำซ้ำโครงสร้างข้อมูล เช่น สไลซ์ .
แสดงถึงบริบทปัจจุบัน ในrange
การกระทำ บริบทปัจจุบันคือส่วนของtodos
. ภายในบล็อก{{ . }}
หมายถึงแต่ละองค์ประกอบในสไลซ์
ใน main.go
ไฟล์ template.ParseFiles
เมธอดใช้ในการสร้างเทมเพลตใหม่จากไฟล์ตั้งแต่หนึ่งไฟล์ขึ้นไป เทมเพลตนี้จะดำเนินการในภายหลังโดยใช้ template.Execute
กระบวนการ; ต้องใช้ io.Writer
และข้อมูลที่จะนำไปใช้กับเทมเพลต
ในตัวอย่างข้างต้น เทมเพลตถูกเรียกใช้งานไปยังเอาต์พุตมาตรฐาน แต่เราสามารถรันไปยังปลายทางใดก็ได้ ตราบใดที่ตรงตาม io.Writer
อินเตอร์เฟซ. ตัวอย่างเช่น หากคุณต้องการส่งคืนผลลัพธ์โดยเป็นส่วนหนึ่งของคำขอเว็บ สิ่งที่คุณต้องทำคือเรียกใช้เทมเพลตไปยัง ResponseWriter
อินเทอร์เฟซดังที่แสดงด้านล่าง
package main
import (
"html/template"
"log"
"net/http"
)
func main() {
t, err := template.ParseFiles("index.html")
if err != nil {
log.Fatal(err)
}
todos := []string{"Watch TV", "Do homework", "Play games", "Read"}
http.HandleFunc("/todos", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/html")
err = t.Execute(w, todos)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
})
http.ListenAndServe(":8080", nil)
}
ส่วนนี้มีขึ้นเพื่อเป็นการแนะนำสั้นๆ เกี่ยวกับแพ็คเกจเทมเพลตของ Go อย่าลืมตรวจสอบเอกสารประกอบสำหรับข้อความ/เทมเพลต และhtml/เทมเพลต หากคุณสนใจกรณีการใช้งานที่ซับซ้อนมากขึ้น
หากคุณไม่ได้ชื่นชอบวิธีการสร้างเทมเพลตของ Go คุณจะมีตัวเลือกอื่น เช่น ห้องสมุด Plush
การทำงานกับ JSON
หากคุณต้องการทำงานกับออบเจ็กต์ JSON คุณจะยินดีที่ทราบว่าไลบรารีมาตรฐานของ Go มีทุกสิ่งที่จำเป็นในการแยกวิเคราะห์และเข้ารหัส JSON ผ่าน encoding/json
แพ็คเกจ
ประเภทเริ่มต้น
เมื่อเข้ารหัสหรือถอดรหัสวัตถุ JSON ใน Go จะมีการใช้ประเภทต่อไปนี้:
bool
สำหรับบูลีน JSONfloat64
สำหรับหมายเลข JSONstring
สำหรับสตริง JSONnil
สำหรับ JSON เป็นโมฆะmap[string]interface{}
สำหรับวัตถุ JSON และ[]interface{}
สำหรับอาร์เรย์ JSON
การเข้ารหัส
ในการเข้ารหัสโครงสร้างข้อมูลเป็น JSON json.Marshal
มีการใช้ฟังก์ชัน นี่คือตัวอย่าง:
package main
import (
"encoding/json"
"fmt"
)
type Person struct {
FirstName string
LastName string
Age int
email string
}
func main() {
p := Person{
FirstName: "Abraham",
LastName: "Freeman",
Age: 100,
email: "[email protected]",
}
json, err := json.Marshal(p)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(string(json))
}
ในโปรแกรมด้านบนนี้ เรามี Person
struct มีสี่ฟิลด์ที่แตกต่างกัน ใน main
ฟังก์ชัน ตัวอย่าง Person
ถูกสร้างขึ้นด้วยฟิลด์ทั้งหมดเริ่มต้น json.Marshal
จะใช้เมธอดเพื่อแปลง p
โครงสร้างเป็น JSON เมธอดนี้ส่งคืนส่วนของไบต์หรือข้อผิดพลาด ซึ่งเราต้องจัดการก่อนเข้าถึงข้อมูล JSON
ในการแปลงส่วนของไบต์เป็นสตริงใน Go เราจำเป็นต้องทำการแปลงประเภทดังที่แสดงไว้ด้านบน การรันโปรแกรมนี้จะสร้างผลลัพธ์ดังต่อไปนี้:
{"FirstName":"Abraham","LastName":"Freeman","Age":100}
อย่างที่คุณเห็น เราได้รับอ็อบเจ็กต์ JSON ที่ถูกต้องซึ่งสามารถใช้ได้ในทุกวิถีทาง โปรดทราบว่า email
ฟิลด์ถูกปล่อยออกจากผลลัพธ์ นี่เป็นเพราะไม่ได้ส่งออกจาก Person
วัตถุโดยอาศัยการขึ้นต้นด้วยตัวพิมพ์เล็ก
โดยค่าเริ่มต้น Go จะใช้ชื่อคุณสมบัติเดียวกันใน struct เป็นชื่อฟิลด์ในวัตถุ JSON นั้น อย่างไรก็ตาม สิ่งนี้สามารถเปลี่ยนแปลงได้โดยใช้แท็ก structfield
type Person struct {
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
Age int `json:"age"`
email string `json:"email"`
}
แท็กฟิลด์ struct ด้านบนระบุว่าตัวเข้ารหัส JSON ควรจับคู่ FirstName
คุณสมบัติใน struct เป็น first_name
ฟิลด์ในวัตถุ JSON เป็นต้น การเปลี่ยนแปลงในตัวอย่างก่อนหน้านี้ทำให้เกิดผลลัพธ์ดังต่อไปนี้:
{"first_name":"Abraham","last_name":"Freeman","age":100}
ถอดรหัส
json.Unmarshal
ฟังก์ชั่นใช้สำหรับถอดรหัสวัตถุ JSON เป็น Gostruct โดยมีลายเซ็นดังต่อไปนี้:
func Unmarshal(data []byte, v interface{}) error
ยอมรับข้อมูล JSON หนึ่งส่วนและสถานที่สำหรับจัดเก็บข้อมูลที่ถอดรหัส หากถอดรหัสสำเร็จ ข้อผิดพลาดที่ส่งคืนจะเป็น nil
.
สมมติว่าเรามีวัตถุ JSON ต่อไปนี้
json := "{"first_name":"John","last_name":"Smith","age":35, "place_of_birth": "London", gender:"male"}"
เราสามารถถอดรหัสเป็น Person
struct ดังที่แสดงด้านล่าง:
func main() {
b := `{"first_name":"John","last_name":"Smith","age":35, "place_of_birth": "London", "gender":"male", "email": "[email protected]"}`
var p Person
err := json.Unmarshal([]byte(b), &p)
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("%+v\n", p)
}
และคุณจะได้ผลลัพธ์ดังต่อไปนี้:
{FirstName:John LastName:Smith Age:35 email:}
Unmarshal
ถอดรหัสเฉพาะฟิลด์ที่พบในประเภทปลายทาง ในกรณีนี้ place_of_birth
และ gender
จะถูกละเว้นเนื่องจากไม่ได้จับคู่กับฟิลด์ struct ใดๆ ใน Person
. ลักษณะการทำงานนี้สามารถใช้ประโยชน์เพื่อเลือกเฉพาะบางฟิลด์เฉพาะจากออบเจ็กต์ JSON ขนาดใหญ่ เช่นเคย ฟิลด์ที่ไม่ถูกเอ็กซ์พอร์ตในโครงสร้างปลายทางจะไม่ได้รับผลกระทบแม้ว่าจะมีฟิลด์ที่สอดคล้องกันในออบเจ็กต์ JSON ก็ตาม นั่นเป็นเหตุผลที่ email
ยังคงเป็นสตริงว่างในผลลัพธ์แม้ว่าจะมีอยู่ในวัตถุ JSON
ฐานข้อมูล
database/sql
แพ็คเกจมีอินเทอร์เฟซทั่วไปรอบฐานข้อมูล SQL (หรือเหมือน SQL) ต้องใช้ร่วมกับโปรแกรมควบคุมฐานข้อมูล เช่น รายการที่ระบุไว้ที่นี่ เมื่อนำเข้าไดรเวอร์ฐานข้อมูล คุณต้องนำหน้าด้วยเครื่องหมายขีดล่าง _
เพื่อเริ่มต้น
ตัวอย่างเช่น นี่คือวิธีใช้แพ็คเกจ MySQLdriver กับ database/sql
:
import (
"database/sql"
_ "github.com/go-sql-driver/mysql"
)
ภายใต้ประทุน ไดรเวอร์จะลงทะเบียนตัวเองว่าพร้อมใช้งานสำหรับdatabase/sql
แพ็คเกจ แต่จะไม่ถูกใช้โดยตรงในรหัสของเรา วิธีนี้ช่วยลดการพึ่งพาไดรเวอร์เฉพาะเพื่อให้สามารถสลับไปใช้ไดรเวอร์อื่นได้อย่างง่ายดายโดยใช้ความพยายามเพียงเล็กน้อย
การเปิดการเชื่อมต่อฐานข้อมูล
ในการเข้าถึงฐานข้อมูล คุณต้องสร้าง sql.DB
วัตถุดังที่แสดงด้านล่าง:
func main() {
db, err := sql.Open("mysql", "user:password@tcp(127.0.0.1:3306)/hello")
if err != nil {
log.Fatal(err)
}
}
sql.Open
วิธีการเตรียมฐานข้อมูลที่เป็นนามธรรมเพื่อใช้ในภายหลัง มันไม่ได้สร้างการเชื่อมต่อกับฐานข้อมูลหรือตรวจสอบพารามิเตอร์การเชื่อมต่อ หากคุณต้องการให้แน่ใจว่าฐานข้อมูลพร้อมใช้งานและสามารถเข้าถึงได้ทันที ให้ใช้ db.Ping()
วิธีการ:
err = db.Ping()
if err != nil {
log.Fatal(err)
}
การปิดการเชื่อมต่อฐานข้อมูล
หากต้องการปิดการเชื่อมต่อฐานข้อมูล คุณสามารถใช้ db.Close()
. โดยปกติคุณต้องการdefer
การปิดฐานข้อมูลจนกว่าฟังก์ชันที่เปิดฐานข้อมูลการเชื่อมต่อจะสิ้นสุดลง โดยปกติแล้วจะเป็น main
ฟังก์ชัน:
func main() {
db, err := sql.Open("mysql", "user:password@tcp(127.0.0.1:3306)/hello")
if err != nil {
log.Fatal(err)
}
defer db.Close()
}
sql.DB
วัตถุถูกออกแบบมาให้มีอายุยืนยาว ดังนั้นคุณจึงไม่ควรเปิดและปิดบ่อยๆ หากคุณทำเช่นนั้น คุณอาจประสบปัญหา เช่น การใช้ซ้ำที่ไม่ดีและการแบ่งปันการเชื่อมต่อ การใช้ทรัพยากรเครือข่ายไม่เพียงพอ ความล้มเหลวเป็นระยะๆ ทางที่ดีควรส่ง sql.DB
วิธีการหรือทำให้ใช้ได้ทั่วโลกและปิดเฉพาะเมื่อโปรแกรมเข้าถึงที่เก็บข้อมูลนั้นเสร็จแล้ว
กำลังดึงข้อมูลจากฐานข้อมูล
การสอบถามตารางสามารถทำได้ในสามขั้นตอน ขั้นแรก เรียก db.Query()
. จากนั้นวนซ้ำในแถว สุดท้าย ใช้ rows.Scan()
เพื่อแยกแต่ละแถวเป็นตัวแปรไม่คงที่ นี่คือตัวอย่าง:
var (
id int
name string
)
rows, err := db.Query("select id, name from users where id = ?", 1)
if err != nil {
log.Fatal(err)
}
defer rows.Close()
for rows.Next() {
err := rows.Scan(&id, &name)
if err != nil {
log.Fatal(err)
}
log.Println(id, name)
}
err = rows.Err()
if err != nil {
log.Fatal(err)
}
หากการสืบค้นส่งคืนแถวเดียว คุณสามารถใช้ db.QueryRow
เมธอดแทน db.Query
และหลีกเลี่ยงโค้ดสำเร็จรูปที่มีความยาวบางส่วนในโค้ดก่อนหน้า:
var (
id int
name string
)
err = db.QueryRow("select id, name from users where id = ?", 1).Scan(&id, &name)
if err != nil {
log.Fatal(err)
}
fmt.Println(id, name)
ฐานข้อมูล NoSQL
Go ยังรองรับฐานข้อมูล NoSQL เป็นอย่างดี เช่น Redis, MongoDB, Cassandra และอื่นๆ แต่ไม่มีอินเทอร์เฟซมาตรฐานสำหรับการทำงานกับพวกมัน คุณจะต้องพึ่งพาแพ็คเกจไดรเวอร์ทั้งหมดสำหรับฐานข้อมูลเฉพาะ ตัวอย่างบางส่วนอยู่ด้านล่าง
- https://github.com/go-redis/redis (ไดรเวอร์ Redis)
- https://github.com/mongodb/mongo-go-driver (ไดรเวอร์ MongoDB)
- https://github.com/gocql/gocql (ไดรเวอร์ Cassandra)
- https://github.com/Shopify/sarama (ไดรเวอร์ Apache Kafka)
สรุป
ในบทความนี้ เราได้พูดถึงประเด็นสำคัญบางประการในการสร้างเว็บแอปพลิเคชันด้วย Go ตอนนี้คุณควรจะสามารถเข้าใจได้ว่าทำไม Goprogrammers หลายคนจึงสาบานด้วยไลบรารีมาตรฐาน มีความครอบคลุมมากและจัดเตรียมเครื่องมือที่จำเป็นสำหรับบริการที่พร้อมสำหรับการผลิต
หากคุณต้องการคำชี้แจงเกี่ยวกับสิ่งที่เรากล่าวถึงที่นี่ โปรดส่งข้อความถึงฉันทาง Twitter ในบทความถัดไปและสุดท้ายในชุดนี้ เราจะพูดถึง go
เครื่องมือและวิธีใช้เพื่อจัดการกับงานทั่วไปในระหว่างการพัฒนาด้วย Go
ขอบคุณสำหรับการอ่านและขอให้สนุกกับการเขียนโค้ด!