در آخرین تغییراتی که در کد ماژول خود ایجاد میکنید، قابلیت دریافت پیام خوشآآمدگویی برای چندین نفر در قالب یک درخواست را اضافه خواهید کرد. به عبارت دیگر، یک ورودی چندمقداری (Multiple-value input) را پردازش کرده و مقادیر آن ورودی را با یک خروجی چندمقداری جفت میکنید. برای انجام این کار، باید مجموعهای از نامها را به تابعی ارسال کنید که بتواند برای هر یک از آنها یک پیام خوشآآمد بازگرداند.
💡 نکته: این موضوع بخشی از یک آموزش چندبخشی است که با بخش «ساخت یک ماژول گو» آغاز میشود.
اما اینجا یک مشکل وجود دارد: تغییر پارامتر تابع Hello از یک نام به مجموعهای از نامها، امضای تابع (Function signature) را تغییر میدهد. اگر ماژول [example.com/greetings](https://example.com/greetings) را قبلاً منتشر کرده بودید و کاربران کدهایی نوشته بودند که Hello را فراخوانی میکرد، این تغییر باعث شکستن و کار نکردن برنامههای آنها میشد.
در چنین شرایطی، انتخاب بهتر این است که یک تابع جدید با نامی متفاوت بنویسید. تابع جدید چند پارامتر دریافت میکند. این کار تابع قدیمی را برای حفظ سازگاری با نسخههای قبلی (Backward compatibility) دستنخورده نگه میدارد.
۱. در فایل greetings/greetings.go کد خود را تغییر دهید تا شبیه به کد زیر شود:
package greetings
import (
"errors"
"fmt"
"math/rand"
)
// Hello returns a greeting for the named person.
func Hello(name string) (string, error) {
// If no name was given, return an error with a message.
if name == "" {
return name, errors.New("empty name")
}
// Create a message using a random format.
message := fmt.Sprintf(randomFormat(), name)
return message, nil
}
// Hellos returns a map that associates each of the named people
// with a greeting message.
func Hellos(names []string) (map[string]string, error) {
// A map to associate names with messages.
messages := make(map[string]string)
// Loop through the received slice of names, calling
// the Hello function to get a message for each name.
for _, name := range names {
message, err := Hello(name)
if err != nil {
return nil, err
}
// In the map, associate the retrieved message with
// the name.
messages[name] = message
}
return messages, nil
}
// randomFormat returns one of a set of greeting messages. The returned
// message is selected at random.
func randomFormat() string {
// A slice of message formats.
formats := []string{
"Hi, %v. Welcome!",
"Great to see you, %v!",
"Hail, %v! Well met!",
}
// Return one of the message formats selected at random.
return formats[rand.Intn(len(formats))]
}
در این کد، شما:
-
یک تابع
Hellosاضافه میکنید که پارامتر ورودی آن به جای یک نام واحد، یک اسلایس از نامها است. همچنین یکی از انواع بازگشتی آن را ازstringبهmapتغییر میدهید تا بتوانید نامهای نگاشتشده به پیامهای خوشآآمدگویی را بازگردانید. -
کاری میکنید که تابع جدید
Hellos، تابع موجودHelloرا فراخوانی کند. این کار به کاهش تکرار کد کمک کرده و در عین حال هر دو تابع را در جای خود حفظ میکند. -
یک Map به نام
messagesایجاد میکنید تا هر یک از نامهای دریافتی (به عنوان کلید / Key) را با پیام تولیدشده (به عنوان مقدار / Value) مرتبط سازد. در گو، یک Map را با ساختارmake(map[key-type]value-type)مقداردهی اولیه میکنید. شما کاری میکنید که تابعHellosاین Map را به فراخواننده بازگرداند. برای اطلاعات بیشتر در مورد Mapها، مقاله Go maps in action را در وبلاگ گو ببینید. -
روی نامهای دریافتی تابع حلقه (Loop) میزنید، بررسی میکنید که هر کدام مقدار غیرخالی داشته باشند، و سپس یک پیام را با هر نام مرتبط میکنید. در این حلقه
for، دستورrangeدو مقدار بازمیگرداند: اندیس (Index) آیتم فعلی در حلقه و یک کپی از مقدار آن آیتم. شما به اندیس نیازی ندارید، بنابراین از شناسه خالی (Blank identifier) در گو (کاراکتر آندرلاین_) برای صرفنظر کردن از آن استفاده میکنید. برای اطلاعات بیشتر، بخش The blank identifier را در Effective Go ببینید.
۲. در کد فراخواننده خود در hello/hello.go، یک اسلایس از نامها را ارسال کنید، سپس محتوای Map دریافت شده (نامها/پیامها) را چاپ کنید.
در فایل hello.go کد خود را تغییر دهید تا شبیه به کد زیر شود:
package main
import (
"fmt"
"log"
"example.com/greetings"
)
func main() {
// Set properties of the predefined Logger, including
// the log entry prefix and a flag to disable printing
// the time, source file, and line number.
log.SetPrefix("greetings: ")
log.SetFlags(0)
// A slice of names.
names := []string{"Gladys", "Samantha", "Darrin"}
// Request greeting messages for the names.
messages, err := greetings.Hellos(names)
if err != nil {
log.Fatal(err)
}
// If no error was returned, print the returned map of
// messages to the console.
fmt.Println(messages)
}
با این تغییرات، شما:
-
یک متغیر
namesاز نوع اسلایس ایجاد میکنید که شامل سه نام است. -
متغیر
namesرا به عنوان آرگومان ورودی به تابعHellosپاس میدهید.
۳. در خط فرمان، به دایرکتوری حاوی hello/hello.go بروید و با استفاده از go run کارکرد صحیح کد را بررسی کنید.
خروجی باید نمایش متنی Map باشد که نامها را به پیامها مرتبط میکند، چیزی شبیه به زیر:
$ go run .
map[Darrin:Hail, Darrin! Well met! Gladys:Hi, Gladys. Welcome! Samantha:Hail, Samantha! Well met!]
این بخش مفاهیم مربوط به Map را برای نشان دادن جفتهای کلید/مقدار معرفی کرد. همچنین ایده حفظ سازگاری با نسخههای قبلی (Backward compatibility) را با پیادهسازی یک تابع جدید برای قابلیتهای جدید یا تغییر یافته در یک ماژول آموزش داد.
این محتوا کاملا رایگان توسط تیم کدلپر ترجمه شده و در اختیار شما کاربران عزیز قرار گرفته است، هر گونه کپی برداری برای مقاصد غیر رایگان و بدون ذکر منبع، مورد پیگیری قانونی قرار میگیرد.
ترجمه شده از منبع: منبع مستندات