برنامه نویسی

آموزش استفاده از Go Modules

توجه: متن اصلی مقاله در پیام شما قرار نگرفته بود و فقط عنوان آن ارسال شده است. محتوای زیر بر اساس ساختار رایج آموزش «How To Use Go Modules» تنظیم شده است. اگر متن دقیق مقاله‌تان را ارسال کنید، ترجمه را دقیقاً مطابق همان نسخه اصلاح می‌کنم.

مقدمه

پکیج‌ها کوچک‌ترین واحدهای نرم‌افزاری قابل اشتراک در Go هستند و در راستای اصول طراحی زبان Go، معمولاً کوچک و متمرکز ساخته می‌شوند. یک پکیج ممکن است فقط یک تابع — مثل تابع Sqrt در پکیج معروف math — را در بر داشته باشد.

به‌طور تاریخی، Go برای پیدا کردن پکیج‌های موردنیاز برنامه، از مسیر GOPATH استفاده می‌کرد؛ راه‌حلی که تا زمان ظهور ماژول‌ها، تنها روش مدیریت وابستگی‌ها در اکوسیستم Go بود. ماژول‌ها از نسخه 1.11 به Go اضافه شدند و با فراهم‌کردن مدیریت نسخه، مدیریت وابستگی‌ها را برای توسعه‌دهندگان بسیار ساده‌تر کردند.

در Go، یک ماژول مجموعه‌ای از پکیج‌ها است که به‌عنوان یک واحد نسخه‌بندی می‌شوند. ماژول‌ها وابستگی‌های موردنیاز خود را در فایلی به نام go.mod ثبت می‌کنند که شامل شناسه ماژول و اطلاعات نسخه‌ها است. سیستم مدیریت وابستگی Go سه قانون مهم دارد:

  1. نسخه‌بندی معنایی (Semantic Versioning): نسخه‌های پکیج‌ها با فرمت vX.Y.Z (نسخه اصلی.فرعی.اصلاحی) مشخص می‌شوند.
  2. واردسازی معنایی نسخه (Semantic Import Versioning): پکیج‌های با نسخه اصلی متفاوت (مثلاً v1 و v2)، مسیرهای Import متفاوتی دارند تا هر دو نسخه بتوانند هم‌زمان در یک برنامه استفاده شوند.
  3. انتخاب نسخه حداقلی (Minimal Version Selection): وقتی چند ماژول به یک وابستگی مشترک نیاز دارند، Go قدیمی‌ترین نسخه‌ای را انتخاب می‌کند که با همه الزامات سازگار است؛ نه جدیدترین نسخه را.

در این آموزش، یک ماژول جدید می‌سازید، به آن وابستگی اضافه می‌کنید، وابستگی‌ها را به نسخه‌های دیگر ارتقا می‌دهید و در نهایت وابستگی‌های بی‌استفاده را حذف می‌کنید.

پیش‌نیازها

  • Go نسخه 1.16 یا بالاتر نصب‌شده. می‌توانید از سری مقالات «راه‌اندازی Go و آماده‌سازی محیط برنامه‌نویسی محلی» برای سیستم‌عامل خود استفاده کنید.
  • تسلط نسبی به مفاهیم پایه Go. مطالعه مقالات «نحوه نوشتن اولین برنامه در Go» و «درک پکیج‌ها در Go» مفید خواهد بود.

مرحله ۱ — ساخت یک ماژول جدید

ابتدا، دایرکتوری‌ای برای پروژه خود بسازید:

mkdir hello
cd hello

سپس با استفاده از دستور go mod init، ماژول جدید خود را راه‌اندازی کنید. این دستور یک شناسه ماژول می‌گیرد که معمولاً مسیر مخزنی است که کد شما در آن میزبانی می‌شود؛ مثل github.com/your_name/hello. اگر قصد انتشار عمومی کد را ندارید، می‌توانید از هر شناسه معنادار دیگری استفاده کنید:

go mod init github.com/your_name/hello
go: creating new go.mod: module github.com/your_name/hello

اجرای این دستور فایل go.mod را می‌سازد؛ فایلی که از این پس قلب پروژه شماست. محتوای آن در ابتدا ساده است:

go.mod

module github.com/your_name/hello

go 1.22
  • خط module شناسه ماژول شما را تعریف می‌کند؛ همان چیزی که سایر ماژول‌ها برای Import کردن پکیج‌های شما استفاده خواهند کرد.
  • خط go حداقل نسخه Go موردنیاز برای کامپایل این ماژول را مشخص می‌کند.

حالا یک فایل main.go بسازید:

nano main.go

main.go

package main

import "fmt"

func main() {
	fmt.Println("Hello, Modules!")
}

برنامه را اجرا کنید:

go run main.go

خروجی:

Hello, Modules!

نکته مهم این است که این پروژه در هیچ جای GOPATH قرار ندارد؛ Go آن را پیدا کرده و اجرا می‌کند؛ چون شناسه ماژول و فایل go.mod مسیر پروژه را تعریف می‌کنند.

مرحله ۲ — افزودن یک وابستگی

قدرت واقعی ماژول‌ها در مدیریت وابستگی‌ها است. بیایید یک پکیج خارجی را به پروژه اضافه کنیم. در این مثال از پکیج github.com/dustin/go-humanize استفاده می‌کنیم که اعداد را به شکل قابل‌فهم برای انسان قالب‌بندی می‌کند.

فایل main.go را تغییر دهید تا از این پکیج استفاده کند:

main.go

package main

import (
	"fmt"

	"github.com/dustin/go-humanize"
)

func main() {
	fmt.Println("Hello, Modules!")
	fmt.Println(humanize.Bytes(1024))
	fmt.Println(humanize.Bytes(5000000))
}

حالا اگر دستور go run main.go را اجرا کنید، Go متوجه می‌شود وابستگی جدیدی در کد Import شده است:

main.go:8:2: no required module provides package github.com/dustin/go-humanize; to add it:
	go get github.com/dustin/go-humanize

خود Go به شما می‌گوید چه کاری باید انجام دهید. دستور پیشنهادی را اجرا کنید:

go get github.com/dustin/go-humanize
go: downloading github.com/dustin/go-humanize v1.0.1
go: added github.com/dustin/go-humanize v1.0.1

و سپس برنامه را اجرا کنید:

go run main.go
Hello, Modules!
1.0 kB
5.0 MB

پکیج go-humanize دو مقدار عددی را به واحدهای قابل‌فهم برای انسان تبدیل کرد. حالا فایل go.mod را بررسی کنید:

go.mod

module github.com/your_name/hello

go 1.22

require github.com/dustin/go-humanize v1.0.1

خط require وابستگی و نسخه دقیق آن را ثبت می‌کند. Go همچنین فایل go.sum را ساخته است؛ فایلی که چک‌سام‌های رمزنگاری‌شده نسخه‌های دانلودشده را نگه می‌دارد تا در اجراهای بعدی، یکسان‌بودن وابستگی‌ها تضمین شود:

github.com/dustin/go-humanize v1.0.1 h1=...
github.com/dustin/go-humanize v1.0.1/go.mod h1=...

توجه: هر دوی فایل‌های go.mod و go.sum باید در سیستم کنترل نسخه (مثل Git) ثبت شوند تا همه سازندگان پروژه از وابستگی‌های کاملاً یکسانی استفاده کنند.

مرحله ۳ — ارتقای وابستگی‌ها به نسخه‌های خاص

وقتی یک وابستگی در مخزن آن (مثلاً GitHub) نسخه جدیدی منتشر کند، نسخه مشخصی را نصب کنید. برای مشاهده نسخه‌های در دسترس یک پکیج، از دستور go list استفاده کنید:

go list -m -versions github.com/dustin/go-humanize
github.com/dustin/go-humanize v1.0.0 v1.0.1

این خروجی فهرست نسخه‌های قابل استفاده را با فرمت نسخه‌بندی معنایی نشان می‌دهد. حالا می‌توانید نسخه دلخواه را با افزودن @version به دستور go get نصب کنید:

go get github.com/dustin/go-humanize@v1.0.1

برای به‌روزرسانی به آخرین نسخه پایدار، از @latest استفاده کنید:

go get github.com/dustin/go-humanize@latest

برای ارتقای همه وابستگی‌های مستقیم و غیرمستقیم به آخرین نسخه‌های ثانویه و اصلاحیِ سازگار:

go get -u

توجه: دستور go get -u نسخه اصلی وابستگی‌ها را ارتقا نمی‌دهد؛ چون طبق قوانین نسخه‌بندی معنایی، نسخه‌های اصلی جدید ممکن است تغییرات ناسازگار (Breaking) داشته باشند. نسخه‌های اصلی همیشه باید صریح و آگاهانه نصب شوند.

توجه: هنگام کار روی پروژه‌های واقعی، از ارتقای کورکورانه همه وابستگی‌ها بپرهیزید و پس از هر ارتقا، تست‌های پروژه را اجرا کنید.

مرحله ۴ — افزودن یک وابستگی با نسخه اصلی جدید

نسخه‌های اصلی (Major) مختلف یک پکیج، مثل v1 و v2، از نظر سیستم مدیریت وابستگی Go کاملاً پکیج‌های متفاوتی محسوب می‌شوند و می‌توانند هم‌زمان در یک برنامه حضور داشته باشند.

برای استفاده از نسخه v2 یک پکیج، باید مسیر Import آن را با پسوند /v2 به‌روزرسانی کنید:

import "github.com/example/pkg/v2"

Go بر اساس این پسوند، نسخه اصلی درست را در فایل go.mod ثبت می‌کند:

require github.com/example/pkg v2.0.0

با این روش، می‌توانید مهاجرت به نسخه جدید را به‌صورت تدریجی انجام دهید؛ ابتدا فقط بخش‌هایی از کد را به /v2 منتقل کنید و پس از اتمام مهاجرت، ارجاعات نسخه قدیمی را حذف کنید.

مرحله ۵ — حذف وابستگی‌های بی‌استفاده

در طول توسعه پروژه، ممکن است Importهایی را که قبلاً اضافه کرده بودید حذف کنید؛ اما وابستگی آن‌ها همچنان در فایل go.mod باقی بماند.

ابتدا استفاده از پکیج را از کد حذف کنید؛ سپس دستور go mod tidy را اجرا کنید:

go mod tidy

این دستور فایل‌های go.mod و go.sum را بررسی کرده و هر وابستگی‌ای را که دیگر در کد شما Import نشده است حذف می‌کند. همچنین هر وابستگی لازمِ جاافتاده را برای پکیج‌هایی که سیستم‌عامل مقصد آن‌ها را در اختیار ندارد (مثل تست‌های مربوط به سایر معماری‌ها) اضافه می‌کند.

استفاده از go mod tidy پیش از هر Commit یا ساخت (Build) نهایی، عمل خوبی است تا فایل‌های ماژول شما همیشه با کد واقعی همگام بمانند.

دستورات پرکاربرد Go Modules

دستورکاربرد
go mod initساخت یک ماژول جدید با شناسه مشخص
go get pkgافزودن یا ارتقای یک وابستگی
go get pkg@versionنصب نسخه مشخصی از یک وابستگی
go get -uارتقای وابستگی‌ها به آخرین نسخه‌های سازگار
go mod tidyحذف وابستگی‌های بی‌استفاده و افزودن وابستگی‌های جاافتاده
go list -m -allفهرست همه وابستگی‌های ماژول
go list -m -versions pkgنمایش نسخه‌های در دسترس یک پکیج
go mod verifyتأیید یکسان‌بودن وابستگی‌های دانلودشده با go.sum
go mod downloadدانلود وابستگی‌ها در حافظه نهان محلی
go mod why pkgنشان‌دادن دلیل نیاز به یک وابستگی
go mod graphنمایش گراف وابستگی‌ها

سوالات متداول

۱. تفاوت go.mod و go.sum چیست؟

فایل go.mod وابستگی‌های مستقیم پروژه شما و نسخه‌هایشان را به‌همراه شناسه ماژول تعریف می‌کند. فایل go.sum چک‌سام‌های رمزنگاری‌شده همه وابستگی‌ها (مستقیم و غیرمستقیم) را نگه می‌دارد تا یکسان‌بودن محتوای دانلودشده در همه محیط‌ها تضمین شود. هر دو فایل باید در کنترل نسخه ثبت شوند.

۲. آیا هنوز به GOPATH نیاز دارم؟

خیر؛ برای توسعه پروژه‌های مبتنی بر ماژول، دیگر لازم نیست کدتان داخل GOPATH قرار گیرد. ماژول‌ها می‌توانند در هر مسیری از سیستم شما زندگی کنند. GOPATH همچنان به‌عنوان محل پیش‌فرض حافظه نهان ماژول‌های دانلودشده ($GOPATH/pkg/mod) استفاده می‌شود.

۳. وقتی چند ماژول به نسخه‌های متفاوتی از یک وابستگی نیاز دارند چه اتفاقی می‌افتد؟

Go نسخه‌ای را انتخاب می‌کند که بر اساس قانون «انتخاب نسخه حداقلی» با همه الزامات سازگار باشد؛ یعنی قدیمی‌ترین نسخه‌ای که نیازهای همه ماژول‌ها را برآورده کند. اگر نسخه‌های اصلی (Major) متفاوتی درگیر باشند — مثلاً v1 و v2 — هر دو می‌توانند هم‌زمان استفاده شوند؛ چون مسیر Import متفاوتی دارند.

۴. go get و go install چه تفاوتی دارند؟

از Go 1.17 به بعد، go get فقط برای افزودن یا به‌روزرسانی وابستگی‌ها در فایل go.mod استفاده می‌شود؛ درحالی‌که go install برای کامپایل و نصب فایل‌های اجرایی در دایرکتوری bin GOPATH به کار می‌رود. برای نصب ابزارهای خط فرمان باید از go install pkg@version استفاده کنید.

جمع‌بندی

در این آموزش، ساخت یک ماژول جدید با go mod init، افزودن وابستگی با go get، نصب نسخه‌های مشخص و ارتقای وابستگی‌ها، استفاده از نسخه‌های اصلی جدید با پسوند /v2 و پاک‌سازی وابستگی‌های بی‌استفاده با go mod tidy را یاد گرفتید.

ماژول‌ها به‌جای محدودیت‌های GOPATH، مدیریت وابستگی نسخه‌دار، تکرارپذیر و امن را به اکوسیستم Go آوردند. با ثبت go.mod و go.sum در کنترل نسخه، هر سازنده‌ای در تیم شما دقیقاً همان وابستگی‌هایی را دریافت می‌کند که شما استفاده کرده‌اید — و این پایه‌ای است برای ساخت اپلیکیشن‌های Go قابل‌نگهداری و قابل‌مقیاس.

نوشته های مشابه

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

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

همچنین ببینید
بستن
دکمه بازگشت به بالا