1. اصول مدیریت بستهها و ماژولها در Go
Go Modules سیستم مدیریت بسته و کنترل نسخه وابستگیها برای زبان Go است. این سیستم از نسخه Go 1.11 معرفی شد و از نسخه 1.13 به بعد به عنوان مکانیزم مدیریت وابستگیها به صورت پیشفرض استفاده میشود. Go Modules هر پروژه را به عنوان یک ماژول مدیریت میکند که شامل کد Go در پروژه و تمامی بستههایی که به آن وابسته هستند میشود.
اصول عملکرد
Go Modules وابستگیهای پروژه را از طریق فایل go.mod
مدیریت میکند. این فایل در ریشه پروژه قرار دارد و تمامی وابستگیهای مستقیم و نسخههای آنها را فهرست میکند. یک ماژول میتواند شامل چندین بسته باشد، اگرچه به طور معمول یک مخازن یک ماژول است.
هنگامی که دستوراتی مانند ساخت یا اجرای دیگر دستورها صادر میشود، اگر فایل go.mod
در دایرکتوری فعلی وجود نداشته باشد، ابزار Go به دنبال فایل go.mod
در دایرکتوری فعلی و دایرکتوریهای والد خود میگردد تا ماژول موضوع برای عملیات فعلی را تعیین کند. در صورت یافتن، از اطلاعات وابستگی موجود در آن فایل برای بازیابی و ساخت بستهها استفاده میشود؛ در غیر این صورت، از روش مدیریت وابستگی در حالت GOPATH استفاده خواهد کرد.
نقش در زبان Go
- کنترل نسخه: Go Modules به توسعهدهندگان اجازه میدهد تا استفاده از نسخههای خاص کتابخانههای شخص ثالث را مشخص کنند و تضمین میکند که امکان بازتولید کد وجود دارد.
- مدیریت بسته: مدیریت آسان وابستگیهای پروژه و نسخههای آنها.
-
جدایی ماژول: پروژههای مختلف میتوانند بر روی نسخههای مختلف یک بسته وابسته داشته باشند بدون تداخل، زیرا هر پروژه فایل
go.mod
مخصوص به خود را برای مدیریت وابستگیها دارد.
مدیریت بسته و ماژول، یک جنبه مهم برای هر زبان برنامهنویسی مدرن است، زیرا وظایفی مانند مدیریت وابستگی، ارتقاء نسخه بستهها و ساخت بازتولیدی برای کاربران بستههای downstream را آسانتر میکند. در زبان Go، هنگامی که اندازه پروژه و وابستگیها ادامه مییابد، Go Modules یک مکانیزم ضروری برای به طور موثر روی کارهای مدیریت وابستگی واقعی میشود.
2. مقدمهای برای ایجاد ماژول Go خود
ایجاد یک ماژول Go جدید بسیار ساده است. میتوانید دستور زیر را در دایرکتوری اصلی پروژه خود اجرا کنید:
go mod init <نام-ماژول>
در اینجا، <نام-ماژول>
معمولاً آدرس مخزن کد مانند github.com/username/repo
است.
هدف فایل go.mod
هنگامی که دستور go mod init
با موفقیت اجرا میشود، یک فایل go.mod
در دایرکتوری فعلی ایجاد میشود. این فایل شامل موارد زیر به ترتیب تعریف میکند:
- نام ماژول فعلی.
- نسخه Go.
- اطلاعات ضروری در مورد تمامی وابستگیهای مستقیم، از جمله نسخه مناسب برای هر بسته.
فایل go.mod
مهمترین مولفه در مکانیزم Go Modules است و به طور خودکار بهروزرسانی میشود زمانی که وابستگیها اضافه یا حذف میشوند.
3. ایجاد و ساختاردهی بستههای Go
3.1 مبانی ایجاد بستهها
در زبان Go، یک بسته شامل چندین فایل منبع Go است که معمولاً در یک دایرکتوری قرار دارند و دارای یک مجموعه خاص از قابلیتها میباشند. هر فایل Go نشان میدهد که با کدام بسته در ارتباط است با استفاده از کلمه کلیدی package
.
برای ایجاد یک بسته جدید، باید:
- یک پوشه برای نمایانگر دایرکتوری بسته ایجاد کنید.
- فایلهای
.go
را در پوشه ایجاد کرده وpackage <نام-بسته>
را در خط اول فایل مشخص کنید.
نام بسته معمولاً مرتبط با نام دایرکتوری است، اما الزامی به یکسان بودن آن نیست. نام بسته باید کوتاه، واضح و بهتر است از استفاده از زیرخط خودداری شود.
3.2 ساختار بسته
ساختاردهی منطقی بستههای Go برای اطمینان از قابلخواندنی، قابلنگهداری و قابلاستفاده بودن کد بسیار اهمیت دارد.
- ساختار دایرکتوری: دایرکتوریها براساس عملکرد تقسیم بندی شدهاند، جایی که هر دایرکتوری یک بسته را نمایندگی میکند.
-
تصاویر اقدامات: دایرکتوریهایی مانند
_test
معمولاً حاوی فایلهای آزمایشی هستند، دایرکتوریcmd
معمولی برای برنامههای خط فرمان استفاده میشود و دایرکتوریinternal
کدهای خصوصی استفاده برای استفاده خارجی نیست.
/directory-ریشه
/pkg
/زیربسته-۱
زیربسته-۱.go
/زیربسته-۲
زیربسته-۲.go
/cmd
main.go // دایرکتوری cmd برای برنامههای خط فرمان
/internal
helper.go
این رویکرد ساختاری بهصورت واضح تر ترکیب کد را نشان میدهد و به مدیریت، آزمایش و کامپایل آنها راحتتر میکند. بستههای ساختاری با این موارد به راحتی میتوانند وارد شوند و توسط پروژههای دیگر استفاده شوند.
پیروی از اصول ساختاری و نامگذاری فوق به توسعهدهندگان دیگر کمک خواهد کرد تا به سرعت ترکیب کد پایه را درک کرده و منجر به مدیریت و نگهداری موثر بسته خواهید شد.
4. وارد کردن و استفاده از بستهها
4.1 وارد کردن بستههای داخلی
فرض کنید که ساختار پروژه شما به صورت زیر است:
├── src
│ ├── main.go
│ └── mypackage
│ └── mymodule.go
در این مثال، mypackage
یک بسته داخلی است که شما ایجاد کردهاید و شامل یک فایل به نام mymodule.go
میباشد. ابتدا اطمینان حاصل کنید که فایل mymodule.go
نام بسته صحیح را اعلام میکند:
// mymodule.go
package mypackage
// SomeFunction یک تابع عمومی در mypackage است
func SomeFunction() {
// پیادهسازی تابع
}
حالا، اگر بخواهیم از SomeFunction
از بسته mypackage
در فایل main.go
استفاده کنیم، باید آن را وارد کنیم:
// main.go
package main
import (
"fmt"
"project/src/mypackage"
)
func main() {
mypackage.SomeFunction()
fmt.Println("تابع فراخوانی شده است")
}
دستور import
بالا بسته mypackage
را به فایل main.go
وارد میکند و به ما امکان میدهد تا از طریق mypackage.SomeFunction
توابع این بسته را فراخوانی کنیم.
4.2 استفاده از بستههای خارجی
هنگام نیاز به پیادهسازی قابلیتهای پیچیدهتر، ما معمولاً به بستههای خارجی وابسته هستیم. بستههای خارجی توسط توسعهدهندگان دیگر نوشته میشوند و به صورت عمومی در دسترس است، که ما میتوانیم به راحتی آنها را در پروژههای خود یکپارچه کنیم. برای پیدا کردن بستههای خارجی، میتوانید به وبسایتهایی مانند godoc.org مراجعه کنید یا در GitHub جستجو کنید.
فرض کنید که میخواهید از gorilla/mux
در پروژهتان استفاده کنید که یک کتابخانه محبوب مسیریابی درخواستهای HTTP است. میتوانید آن را به صورت زیر وارد کرده و استفاده کنید:
ابتدا، بسته را با استفاده از دستور go get
نصب کنید:
go get -u github.com/gorilla/mux
سپس، آن را وارد کرده و در کد خود استفاده کنید:
package main
import (
"net/http"
"github.com/gorilla/mux"
)
func main() {
r := mux.NewRouter() // ایجاد نمونه مسیریاب
// افزودن قوانین مسیر
r.HandleFunc("/", func(w http.ResponseWriter, r *http.Request){
w.Write([]byte("به gorilla/mux خوش آمدید!"))
})
// شروع سرور HTTP
http.ListenAndServe(":8000", r)
}
در کد بالا، ما gorilla/mux
را وارد کرده و یک مسیریاب HTTP ایجاد میکنیم، یک تابع دستگیرنده برای مسیر ریشه تعریف میکنیم و در نهایت سرور را در پورت 8000 با استفاده از http.ListenAndServe
راهاندازی میکنیم.
5. مدیریت وابستگیهای ماژول
در یک پروژه بزرگ، مدیریت وابستگیهای ماژول به ویژه مهم است. این کمک میکند تا اطمینان حاصل شود که هر ساخت یا نمونه پروژه میتواند از همان نسخههای وابستگیها به صورت دقیق استفاده کند تا همگرایی حاکم باشد.
5.1 بهروزرسانی وابستگیها با go get
دستور go get
نه تنها میتواند وابستگیهای بسته را اضافه کند، بلکه میتواند وابستگیهای موجود را نیز بهروز کند. گزینههای معمول زیر برای go get
وجود دارند:
- بهروزرسانی یک بسته تکی:
go get -u github.com/some/package
- بهروزرسانی همه وابستگیهای این بسته:
go get -u github.com/some/package/...
- بهروزرسانی همه وابستگیها در پروژه:
go get -u ./...
- دانلود اما نصب نکن:
go get -d github.com/some/package
هنگام انجام عملیات بهروزرسانی، Go وابستگیها را به آخرین نسخههای دقیق یا تجدید نسخه خواهد کرد (براساس ورژنبندی نشانهای) و تغییرات همچنین در فایل go.mod
نیز قابل مشاهده خواهد بود.
کنترل نسخه 5.2 و go.mod
از نسخه 1.11 به بعد، Go یک سیستم مدیریت وابستگی جدید به نام Go Modules
ارائه داده است. در دایرکتوری اصلی پروژه، فایل go.mod
وابستگیهای بستهها را ثبت میکند.
فایل go.mod
شامل بخشهای زیر است:
- ماژول مسیر ماژول برای پروژه فعلی را اعلام میکند.
- نیاز اعلام وابستگیها و نسخههای خاص آنها را مشخص میکند.
- جایگزین میتواند مسیرها و نسخههای جایگزین را مشخص کند.
- استثنا برای حذف نسخههای خاص استفاده میشود.
یک نمونه از یک فایل go.mod
ممکن است به این شکل باشد:
module github.com/my/awesome-project
go 1.14
require (
github.com/gorilla/mux v1.7.4
golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975
)
replace (
github.com/old/dependency => github.com/new/dependency v1.2.3
)
exclude (
github.com/old/dependency v1.1.4
)
هنگام اجرای دستورات مانند go build
یا go test
در پروژه، Go به طور خودکار فایل go.mod
را تولید یا بهروزرسانی میکند تا تمام وابستگیهای مورد نیاز برای پروژه را تعیین کند. بهترین روش در کنترل نسخه، این است که به طور منظم فایلهای go.mod
و go.sum
(که هشهای رمزنگاری مورد انتظار وابستگیها را ثبت میکند) را commit کنید.
با مدیریت از طریق فایل go.mod
، اطمینان حاصل میشود که هر توسعهدهنده در یک تیم از همان نسخههای وابستگی استفاده میکند، از این رو به وضعیت "ولی توی ماشین من کار میکنه" پرهیز میشود.