تغییرات اخیر

در اینجا اطلاعیه‌ها، نسخه‌ها و تغییرات جدید لیارا فهرست می‌شوند.

    آموزش ساخت RESTful API با Go


    ۱۸ اردیبهشت ۱۴۰۰
    آموزش ساخت restful api با go

    در این مقاله‌ی آموزشی می‌خواهیم با زبان برنامه‌نویسی Go یک RESTful API توسعه دهیم که به کمک آن می‌توانید رویدادها را مدیریت کنید.

    پیش‌نیازها

    • فرض ما بر این است که شما از قبل با زبان Go آشنا شده‌اید و در حال حاضر این زبان برنامه‌نویسی بر روی سیستم شما نصب است.
    • پس از نصب زبان Go باید در GOPATH که اکثر افراد تمام پروژه‌هایشان را در این مسیر نگهداری می‌کنند، پروژه‌ی فعلی را توسعه دهیم بنابراین در پوشه‌ی src می‌توانید یک فولدر خاص برای این پروژه ایجاد کنید یا برای ساماندهی بیشتر پروژه‌های مختلف یک پوشه با نام github.com ایجاد کنید و در آن پوشه‌ی دیگری ایجاد کنید و نام آن را همان نام کاربری خود در GitHub قرار دهید. در نهایت در مسیر GOPATH/src/github.com/<Github username> یک پوشه‌ی جدید برای پروژه‌ی فعلی با نام دلخواه ایجاد کنید.

    مقاله‌ی مرتبط: توسعه و اجرای اولین برنامه با زبان Go

    توسعه‌ی API

    برای پیاده‌سازی ساختار اولیه‌ی پروژه می‌توانید به شکل زیر عمل کنید:

    mkdir go-rest-api
    cd go-rest-api
    touch main.go

    پس از ایجاد کردن فایل main.go از یک ویرایشگر کد برای توسعه‌ی برنامه کمک می‌گیریم و کدهای زیر را در فایل ایجاد شده قرار می‌دهیم:

    package main
    
    import "fmt"
    
    func main() {
    	fmt.Println("Hello World!")
    }

    برای کامپایل این برنامه ساده می‌توانید در Terminal فعلی دستور go build را اجرا کرده و درنهایت به شکل زیر برنامه‌ی کامپایل شده را اجرا کنید:

    ./go-rest-api

    انتظار می‌رود که خروجی زیر در Terminal شما چاپ شود:

    Hello World!

    راه‌اندازی سرور HTTP با استفاده از Gorilla Mux

    Gorilla Mux یک پکیج است که به شما امکان می‌دهد routeهای مورد نیاز برنامه را ایجاد کرده و هر کدام از درخواست‌های ورودی را به Controller مربوطه ارجاع دهید. قبل از کار با پکیج Mux باید آن را به شکل زیر نصب کرده:

    go mod init
    go get -u github.com/gorilla/mux

    و در مرحله‌ی بعد اولین endpoint برنامه را تعریف کنیم:

    package main
    
    import (
    	"fmt"
    	"log"
    	"net/http"
    
    	"github.com/gorilla/mux"
    )
    
    func homeLink(w http.ResponseWriter, r *http.Request) {
    	fmt.Fprintf(w, "Welcome home!")
    }
    
    func main() {
    	router := mux.NewRouter().StrictSlash(true)
    	router.HandleFunc("/", homeLink)
    	log.Fatal(http.ListenAndServe(":8080", router))
    }

    مطمئنا پس از ایجاد هر تغییری در کدها باید برنامه را مجددا اجرا کنید. حال برای اجرای برنامه دو راه حل وجود دارد که یکی از آن‌ها کامپایل برنامه و اجرای برنامه‌ی کامپایل شده است اما برای سریع‌تر شدن فرایند تست برنامه می‌توانید دستور go run main.go را اجرا کنید که بدون نیاز به کامپایل، سرور توسعه داده شده را برای شما اجرا می‌کند.

    خروجی مورد انتظار پس از راه‌اندازی و ارسال درخواست GET به برنامه در آدرس localhost:8080 به شکل زیر است.

    راه‌اندازی سرور با استفاده از mux

    شبیه‌سازی دیتابیس

    برای شبیه‌سازی دیتابیس می‌توانیم رویداد‌ها را به شکل زیر در برنامه تعریف کنیم:

    type event struct {
    	ID          string `json:"ID"`
    	Title       string `json:"Title"`
    	Description string `json:"Description"`
    }
    
    type allEvents []event
    
    var events = allEvents{
    	{
    		ID:          "1",
    		Title:       "Introduction to Golang",
    		Description: "Come join us for a chance to learn how golang works and get to eventually try it out",
    	},
    }

    در این ساختار فقط از ID، Title و Description برای ذخیره‌ی رویدادها استفاده کرده‌ایم و در ادامه کدهای مربوط به اضافه کردن، به‌روزرسانی و حذف رویدادها را پیاده‌سازی خواهیم کرد.

    اضافه کردن یک رویداد جدید

    برای ایجاد یک رویداد جدید باید داده‌های ارسال شده به‌صورت POST را دریافت کرده و به دیتابیس شبیه‌سازی شده اضافه کنیم. در مرحله‌ی بعد پس از اضافه شدن موفقیت‌آمیز رویداد به دیتابیس شبیه‌سازی شده، همان رویداد را با status code شماره‌ی 201 به کاربر برمی‌گردانیم:

    package main
    
    import (
    	"encoding/json"
    	"fmt"
    	"io/ioutil"
    	"log"
    	"net/http"
    
    	"github.com/gorilla/mux"
    )
    
    type event struct {
    	ID          string `json:"ID"`
    	Title       string `json:"Title"`
    	Description string `json:"Description"`
    }
    
    type allEvents []event
    
    var events = allEvents{
    	{
    		ID:          "1",
    		Title:       "Introduction to Golang",
    		Description: "Come join us for a chance to learn how golang works and get to eventually try it out",
    	},
    }
    
    func createEvent(w http.ResponseWriter, r *http.Request) {
    	var newEvent event
    	// Convert r.Body into a readable formart
    	reqBody, err := ioutil.ReadAll(r.Body)
    	if err != nil {
    		fmt.Fprintf(w, "Kindly enter data with the event id, title and description only in order to update")
    	}
    
    	json.Unmarshal(reqBody, &newEvent)
    
    	// Add the newly created event to the array of events
    	events = append(events, newEvent)
    
    	// Return the 201 created status code
    	w.WriteHeader(http.StatusCreated)
    	// Return the newly created event
    	json.NewEncoder(w).Encode(newEvent)
    }
    
    func homeLink(w http.ResponseWriter, r *http.Request) {
    	fmt.Fprintf(w, "Welcome home!")
    }
    
    func main() {
    	router := mux.NewRouter().StrictSlash(true)
    	router.HandleFunc("/", homeLink)
    	router.HandleFunc("/event", createEvent).Methods("POST")
    	log.Fatal(http.ListenAndServe(":8080", router))
    }
    
    اضافه کردن یک رویداد جدید به برنامه

    نمایش تمام رویداد‌ها

    برای نمایش تمام رویداد‌ها باید داده‌‌های events را نمایش دهیم:

    package main
    
    import (
    	"encoding/json"
    	"fmt"
    	"io/ioutil"
    	"log"
    	"net/http"
    
    	"github.com/gorilla/mux"
    )
    
    type event struct {
    	ID          string `json:"ID"`
    	Title       string `json:"Title"`
    	Description string `json:"Description"`
    }
    
    type allEvents []event
    
    var events = allEvents{
    	{
    		ID:          "1",
    		Title:       "Introduction to Golang",
    		Description: "Come join us for a chance to learn how golang works and get to eventually try it out",
    	},
    }
    
    func homeLink(w http.ResponseWriter, r *http.Request) {
    	fmt.Fprintf(w, "Welcome home!")
    }
    
    func createEvent(w http.ResponseWriter, r *http.Request) {
    	var newEvent event
    	// Convert r.Body into a readable formart
    	reqBody, err := ioutil.ReadAll(r.Body)
    	if err != nil {
    		fmt.Fprintf(w, "Kindly enter data with the event id, title and description only in order to update")
    	}
    
    	json.Unmarshal(reqBody, &newEvent)
    
    	// Add the newly created event to the array of events
    	events = append(events, newEvent)
    
    	// Return the 201 created status code
    	w.WriteHeader(http.StatusCreated)
    	// Return the newly created event
    	json.NewEncoder(w).Encode(newEvent)
    }
    
    func getAllEvents(w http.ResponseWriter, r *http.Request) {
    	json.NewEncoder(w).Encode(events)
    }
    
    func main() {
    	router := mux.NewRouter().StrictSlash(true)
    	router.HandleFunc("/", homeLink)
    	router.HandleFunc("/event", createEvent).Methods("POST")
    	router.HandleFunc("/events", getAllEvents).Methods("GET")
    	log.Fatal(http.ListenAndServe(":8080", router))
    }
    دریافت تمام رویدادها از سرور

    نمایش یک رویداد خاص

    برای نمایش یک رویداد خاص باید باید مقدار ID را به‌کمک Mux دریافت کنیم و درنهایت اگر ID ارسال شده با رویدادهای موجود در دیتابیس شبیه‌سازی شده همخوانی داشت، تمام داده‌های آن رویداد را نمایش دهیم:

    package main
    
    import (
    	"encoding/json"
    	"fmt"
    	"io/ioutil"
    	"log"
    	"net/http"
    
    	"github.com/gorilla/mux"
    )
    
    type event struct {
    	ID          string `json:"ID"`
    	Title       string `json:"Title"`
    	Description string `json:"Description"`
    }
    
    type allEvents []event
    
    var events = allEvents{
    	{
    		ID:          "1",
    		Title:       "Introduction to Golang",
    		Description: "Come join us for a chance to learn how golang works and get to eventually try it out",
    	},
    }
    
    func homeLink(w http.ResponseWriter, r *http.Request) {
    	fmt.Fprintf(w, "Welcome home!")
    }
    
    func createEvent(w http.ResponseWriter, r *http.Request) {
    	var newEvent event
    	// Convert r.Body into a readable formart
    	reqBody, err := ioutil.ReadAll(r.Body)
    	if err != nil {
    		fmt.Fprintf(w, "Kindly enter data with the event id, title and description only in order to update")
    	}
    
    	json.Unmarshal(reqBody, &newEvent)
    
    	// Add the newly created event to the array of events
    	events = append(events, newEvent)
    
    	// Return the 201 created status code
    	w.WriteHeader(http.StatusCreated)
    	// Return the newly created event
    	json.NewEncoder(w).Encode(newEvent)
    }
    
    func getOneEvent(w http.ResponseWriter, r *http.Request) {
    	// Get the ID from the url
    	eventID := mux.Vars(r)["id"]
    
    	// Get the details from an existing event
    	// Use the blank identifier to avoid creating a value that will not be used
    	for _, singleEvent := range events {
    		if singleEvent.ID == eventID {
    			json.NewEncoder(w).Encode(singleEvent)
    		}
    	}
    }
    
    func getAllEvents(w http.ResponseWriter, r *http.Request) {
    	json.NewEncoder(w).Encode(events)
    }
    
    func main() {
    	router := mux.NewRouter().StrictSlash(true)
    	router.HandleFunc("/", homeLink)
    	router.HandleFunc("/event", createEvent).Methods("POST")
    	router.HandleFunc("/events", getAllEvents).Methods("GET")
    	router.HandleFunc("/events/{id}", getOneEvent).Methods("GET")
    	log.Fatal(http.ListenAndServe(":8080", router))
    }
    دریافت یک رویداد خاص از سرور

    به‌روزرسانی یک رویداد

    برای به‌روزرسانی یک رویداد دقیقا شبیه بخش قبل عمل می‌کنیم و از Mux برای دریافت ID استفاده خواهیم کرد. اگر رویدادی با این ID وجود داشته باشد، به‌سراغ مقادیر ارسال شده در بدنه‌ی درخواست PATCH می‌رویم و آن‌ها را با مقادیر فعلی رویداد جایگزین می‌کنیم. درنهایت رویداد به‌روزرسانی شده را نمایش می‌دهیم:

    package main
    
    import (
    	"encoding/json"
    	"fmt"
    	"io/ioutil"
    	"log"
    	"net/http"
    
    	"github.com/gorilla/mux"
    )
    
    type event struct {
    	ID          string `json:"ID"`
    	Title       string `json:"Title"`
    	Description string `json:"Description"`
    }
    
    type allEvents []event
    
    var events = allEvents{
    	{
    		ID:          "1",
    		Title:       "Introduction to Golang",
    		Description: "Come join us for a chance to learn how golang works and get to eventually try it out",
    	},
    }
    
    func homeLink(w http.ResponseWriter, r *http.Request) {
    	fmt.Fprintf(w, "Welcome home!")
    }
    
    func createEvent(w http.ResponseWriter, r *http.Request) {
    	var newEvent event
    	// Convert r.Body into a readable formart
    	reqBody, err := ioutil.ReadAll(r.Body)
    	if err != nil {
    		fmt.Fprintf(w, "Kindly enter data with the event id, title and description only in order to update")
    	}
    
    	json.Unmarshal(reqBody, &newEvent)
    
    	// Add the newly created event to the array of events
    	events = append(events, newEvent)
    
    	// Return the 201 created status code
    	w.WriteHeader(http.StatusCreated)
    	// Return the newly created event
    	json.NewEncoder(w).Encode(newEvent)
    }
    
    func getOneEvent(w http.ResponseWriter, r *http.Request) {
    	// Get the ID from the url
    	eventID := mux.Vars(r)["id"]
    
    	// Get the details from an existing event
    	// Use the blank identifier to avoid creating a value that will not be used
    	for _, singleEvent := range events {
    		if singleEvent.ID == eventID {
    			json.NewEncoder(w).Encode(singleEvent)
    		}
    	}
    }
    
    func getAllEvents(w http.ResponseWriter, r *http.Request) {
    	json.NewEncoder(w).Encode(events)
    }
    
    func updateEvent(w http.ResponseWriter, r *http.Request) {
    	// Get the ID from the url
    	eventID := mux.Vars(r)["id"]
    	var updatedEvent event
    	// Convert r.Body into a readable formart
    	reqBody, err := ioutil.ReadAll(r.Body)
    	if err != nil {
    		fmt.Fprintf(w, "Kindly enter data with the event title and description only in order to update")
    	}
    
    	json.Unmarshal(reqBody, &updatedEvent)
    
    	for i, singleEvent := range events {
    		if singleEvent.ID == eventID {
    			singleEvent.Title = updatedEvent.Title
    			singleEvent.Description = updatedEvent.Description
    			events[i] = singleEvent
    			json.NewEncoder(w).Encode(singleEvent)
    		}
    	}
    }
    
    func main() {
    	router := mux.NewRouter().StrictSlash(true)
    	router.HandleFunc("/", homeLink)
    	router.HandleFunc("/event", createEvent).Methods("POST")
    	router.HandleFunc("/events", getAllEvents).Methods("GET")
    	router.HandleFunc("/events/{id}", getOneEvent).Methods("GET")
    	router.HandleFunc("/events/{id}", updateEvent).Methods("PATCH")
    	log.Fatal(http.ListenAndServe(":8080", router))
    }
    به‌روزرسانی یک رویداد

    حذف یک رویداد

    حذف یک رویداد با متد DELETE انجام می‌شود بنابراین مقدار ID ارسال شده در درخواست‌هایی با متد DELETE را به کمک Mux دریافت خواهیم کرد و آن را با دیتابیس شبیه‌سازی شده مقایسه می‌کنیم. اگر در دیتابیس ما رویدادی با این ID وجود داشته باشد آن را حذف خواهیم کرد و درنهایت موفقیت‌آمیز بودن حذف رویداد را نمایش می‌دهیم:

    package main
    
    import (
    	"encoding/json"
    	"fmt"
    	"io/ioutil"
    	"log"
    	"net/http"
    
    	"github.com/gorilla/mux"
    )
    
    type event struct {
    	ID          string `json:"ID"`
    	Title       string `json:"Title"`
    	Description string `json:"Description"`
    }
    
    type allEvents []event
    
    var events = allEvents{
    	{
    		ID:          "1",
    		Title:       "Introduction to Golang",
    		Description: "Come join us for a chance to learn how golang works and get to eventually try it out",
    	},
    }
    
    func homeLink(w http.ResponseWriter, r *http.Request) {
    	fmt.Fprintf(w, "Welcome home!")
    }
    
    func createEvent(w http.ResponseWriter, r *http.Request) {
    	var newEvent event
    	// Convert r.Body into a readable formart
    	reqBody, err := ioutil.ReadAll(r.Body)
    	if err != nil {
    		fmt.Fprintf(w, "Kindly enter data with the event id, title and description only in order to update")
    	}
    
    	json.Unmarshal(reqBody, &newEvent)
    
    	// Add the newly created event to the array of events
    	events = append(events, newEvent)
    
    	// Return the 201 created status code
    	w.WriteHeader(http.StatusCreated)
    	// Return the newly created event
    	json.NewEncoder(w).Encode(newEvent)
    }
    
    func getOneEvent(w http.ResponseWriter, r *http.Request) {
    	// Get the ID from the url
    	eventID := mux.Vars(r)["id"]
    
    	// Get the details from an existing event
    	// Use the blank identifier to avoid creating a value that will not be used
    	for _, singleEvent := range events {
    		if singleEvent.ID == eventID {
    			json.NewEncoder(w).Encode(singleEvent)
    		}
    	}
    }
    
    func getAllEvents(w http.ResponseWriter, r *http.Request) {
    	json.NewEncoder(w).Encode(events)
    }
    
    func updateEvent(w http.ResponseWriter, r *http.Request) {
    	// Get the ID from the url
    	eventID := mux.Vars(r)["id"]
    	var updatedEvent event
    	// Convert r.Body into a readable formart
    	reqBody, err := ioutil.ReadAll(r.Body)
    	if err != nil {
    		fmt.Fprintf(w, "Kindly enter data with the event title and description only in order to update")
    	}
    
    	json.Unmarshal(reqBody, &updatedEvent)
    
    	for i, singleEvent := range events {
    		if singleEvent.ID == eventID {
    			singleEvent.Title = updatedEvent.Title
    			singleEvent.Description = updatedEvent.Description
    			events[i] = singleEvent
    			json.NewEncoder(w).Encode(singleEvent)
    		}
    	}
    }
    
    func deleteEvent(w http.ResponseWriter, r *http.Request) {
    	// Get the ID from the url
    	eventID := mux.Vars(r)["id"]
    
    	// Get the details from an existing event
    	// Use the blank identifier to avoid creating a value that will not be used
    	for i, singleEvent := range events {
    		if singleEvent.ID == eventID {
    			events = append(events[:i], events[i+1:]...)
    			fmt.Fprintf(w, "The event with ID %v has been deleted successfully", eventID)
    		}
    	}
    }
    
    func main() {
    	router := mux.NewRouter().StrictSlash(true)
    	router.HandleFunc("/", homeLink)
    	router.HandleFunc("/event", createEvent).Methods("POST")
    	router.HandleFunc("/events", getAllEvents).Methods("GET")
    	router.HandleFunc("/events/{id}", getOneEvent).Methods("GET")
    	router.HandleFunc("/events/{id}", updateEvent).Methods("PATCH")
    	router.HandleFunc("/events/{id}", deleteEvent).Methods("DELETE")
    	log.Fatal(http.ListenAndServe(":8080", router))
    }
    
    حذف یک رویداد

    منبع: https://medium.com/the-andela-way/build-a-restful-json-api-with-golang-85a83420c9da

    همچنین بخوانید: معرفی هاست رایگان Golang

    برچسب‌ها:

    ســــــــــــــــــــــال‌هاست که هستیم

    ۶ سال در کنار شما تجربه جمع کردیم. تازه در ابتدای مسیر هستیم، مسیر ساخت آینده.

    جمع‌مـــــــــــان، جمع است

    بیش از ۴۰ هزار توسعه‌دهنده و صاحبان کسب و کار در جمع ما هستند. جای شما خالی‌ست...

    خدمات رایگان لیارا

    ۲.۵ گیگابایت فضای ذخیره‌سازی ابری رایگان

    ۲.۵ گیگابایت Object Storage سازگار با پروتکل S3 با دیسک‌های SSD به‌صورت رایگان دریافت کنید.

    هاست رایگان برای دیتابیس‌

    دیتابیس‌های MariaDB، PostgreSQL و Redis را فقط با یک کلیک و به‌صورت رایگان تهیه کنید.

    سرویس DNS رایگان

    به سادگی دامنه‌تان را اضافه کنید و به صورت رایگان رکورد‌های آن را مدیریت کنید.

    ۱۰۰ هزار تومان اعتبار اولیه

    بعد از ثبت نام در لیارا مبلغ ۱۰۰ هزار تومان اعتبار هدیه دریافت می‌کنید که با توجه به ساعتی بودن هزینه سرویس‌ها، می‌توانید تمامی خدمات پولی را برای چندین هفته رایگان استفاده کنید.

    ارسال ۱۰۰ ایمیل تراکنشی رایگان در هر ماه

    در سرویس ایمیل لیارا شما می‌توانید تا ۱۰۰ ایمیل رایگان در هر ماه ارسال کنید. (به‌همراه دسترسی SMTP)

    هاست رایگان برای انواع وبسایت

    تفاوتی ندارد برای وبسایت خود از Node استفاده می‌کنید یا Laravel و Django، در لیارا می‌توانید به صورت کاملا رایگان آن را میزبانی کنید.

    همراه شما هستیم

    در خصوص سفارش یا استفاده از سرویس‌ها سوالی دارید؟
    تلفن واحد فروش:
    ۰۲۵-۳۳۵۵۷۶۱۹ (روزهای کاری ۹ الی ۱۷)
    تلفن واحد فروش: ۳۳۵۵۷۶۱۹-۰۲۵ (روزهای کاری ۹ الی ۱۷)