إدارة الحزم باستخدام وحدات Go: دليل عملي

تحية للجميع. تحسبًا لبدء دورة Golang Developer ، قمنا بإعداد ترجمة أخرى مثيرة للاهتمام لك.



الوحدات هي طريقة للتعامل مع التبعيات في Go. مقدمة في البداية كتجربة ، من المفترض أن يتم إدخال الوحدات في الحقل كمعيار جديد لإدارة الحزم من الإصدار 1.13.

أجد هذا الموضوع غير عادي بما فيه الكفاية للمبتدئين القادمين من لغات أخرى ، لذلك قررت جمع بعض الأفكار والنصائح هنا لمساعدة الآخرين مثلي في الحصول على فكرة عن إدارة الحزم في Go. سنبدأ بمقدمة عامة ، ثم ننتقل إلى جوانب أقل وضوحًا ، بما في ذلك استخدام مجلد البائع ، واستخدام الوحدات مع Docker في التطوير ، وتبعيات الأداة ، وما إلى ذلك.

إذا كنت معتادًا على وحدات Go وتعرف على Wiki، مثل الجزء الخلفي من يدك ، ربما لن تكون هذه المقالة مفيدة جدًا لك. ولكن بالنسبة للبقية ، يمكن أن يوفر عدة ساعات من التجربة والخطأ.

لذا إذا كنت في الطريق ، اقفز واستمتع بالرحلة.



بداية سريعة


إذا كان عنصر تحكم الإصدار مدمجًا بالفعل في مشروعك ، فيمكنك ببساطة تشغيله

go mod init

أو حدد المسار إلى الوحدة يدويًا. هذا شيء يشبه الاسم وعنوان URL ومسار الاستيراد لحزمتك:

go mod init github.com/you/hello

سيؤدي هذا إلى إنشاء ملف go.mod، والذي يحدد أيضًا متطلبات المشروع و lochit اعتمادًا على نسختهم الصحيحة (كقياس بالنسبة لك ، فهو مثل package.json، ومدمج package-lock.jsonفي ملف واحد):

module github.com/you/hello
go 1.12

اركض go getلإضافة تبعية جديدة لمشروعك:

لاحظ أنه على الرغم من أنه لا يمكنك تحديد نطاق من الإصدارات مع go get ، فإن ما تحدده هنا ليس إصدارًا محددًا ، بل إصدارًا أدنى. كما سنرى لاحقًا ، هناك طريقة لتحديث التبعيات برفق وفقًا لـ semver.

# use Git tags
go get github.com/go-chi/chi@v4.0.1
# or Git branch name
go get github.com/go-chi/chi@master
# or Git commit hash
go get github.com/go-chi/chi@08c92af

الآن ملفنا go.modكما يلي:

module github.com/you/hello
go 1.12
require github.com/go-chi/chi v4.0.2+incompatible // indirect

تتم +incompatibleإضافة اللاحقة إلى جميع الحزم التي لم يتم تكوينها بعد لوحدات Go أو تنتهك قواعد التحكم في الإصدار.

نظرًا لأننا لم نستورد هذه الحزمة في أي مكان في مشروعنا ، فقد تم وضع علامة عليها كـ // indirect. يمكننا ترتيب ذلك بالأمر التالي:

go mod tidy

بناءً على الحالة الحالية لمستودعك ، فإنه إما يحذف وحدة غير مستخدمة أو يحذف تعليقًا // indirect.

إذا لم يكن هناك أي تبعية في حد ذاتها go.mod(على سبيل المثال ، لم يتم تكوينها بعد للوحدات النمطية) ، فسيتم كتابة جميع تبعياتها إلى الملف الأصلي go.mod(كخيار ، ملفك go.mod)مع تعليق // indirectللإشارة إلى أنها ليست من الاستيراد المباشر في الوحدة النمطية الخاصة بك. على

الصعيد العالمي ، الهدف go mod tidyهو أيضًا إضافة أي تبعيات مطلوبة لمجموعات أنظمة التشغيل الأخرى ، والبنى وعلامات التجميع. تأكد من تشغيلها قبل كل إصدار. واحذر

أيضًا من أنه بعد إضافة التبعية تم إنشاء ملفgo.sum. قد تعتقد أن هذا ملف قفل. ولكن في الواقع ، go.modتوفر بالفعل معلومات كافية للبنى القابلة للتكرار بنسبة 100٪. go.sumيتم إنشاء الملف لأغراض التحقق: فهو يحتوي على المجموع الاختباري التشفير المتوقع لمحتويات الإصدارات الفردية للوحدة النمطية.

جزئيا لأنه go.sumليس ملف قفل ، فإنه يحفظ الاختبارية المكتوبة لإصدار الوحدة النمطية حتى بعد التوقف عن استخدام هذه الوحدة. يتيح لك ذلك التحقق من المجموع الاختباري إذا استأنفت استخدامه لاحقًا ، مما يوفر أمانًا إضافيًا.


انتقل Mkcert للتو إلى الوحدات (مع البائع / للتوافق مع الإصدارات السابقة) وسار كل شيء بسلاسة
https://github.com/FiloSottile/mkcert/commit/26ac5f35395fb9cba3805faf1a5a04d260271291

$ GO111MODULE=on go1.11rc1 mod init
$ GO111MODULE=on go1.11rc1 mod vendor
$ git add go.mod go.sum vendor
$ git rm Gopkg.lock Gopkg.toml Makefile



الأسئلة الشائعة: هل يجب أن أرتكب go.sumفي git؟
ج: نعم بالتأكيد. مع ذلك ، لا يحتاج أصحاب مصادرك إلى الوثوق بمستودعات GitHub الأخرى وأصحاب مسارات الاستيراد المخصصة. بالفعل في طريقنا إلينا ، هناك شيء أفضل ، ولكن في الوقت الحالي هذا هو نفس طراز التجزئة في ملفات القفل.

و go buildو الأوامر go testسوف تلقائيا تحميل كافة التبعيات في عداد المفقودين، على الرغم من أنك يمكن أن تفعل ذلك صراحة بمساعدة go mod download-ملء ما قبل مخابئ المحلية التي قد تكون مفيدة لCI.

بشكل افتراضي ، يتم تحميل جميع حزمنا من جميع المشاريع في الدليل $GOPATH/pkg/mod. سنناقش هذا بمزيد من التفاصيل في وقت لاحق.

ترقية إصدارات الحزمة


يمكنك استخدام go get -uإما go get -u=patchلتحديث التبعيات إلى أحدث إصدار ثانوي أو التصحيح ، على التوالي.

ولكن لا يمكنك الترقية إلى إصدارات رئيسية مثل هذا. يجب أن يتوافق الرمز المتضمن في وحدات Go من الناحية الفنية مع القواعد التالية:

  • مطابقة semver (مثال العلامة VCS v1.2.3).
  • إذا كانت الوحدة النمطية هي الإصدار v2 أو أعلى ، فيجب تضمين الإصدار الرئيسي من الوحدة النمطية /vNفي نهاية مسار الوحدة النمطية المستخدمة في الملف go.modوفي مسار استيراد الحزمة:

import "github.com/you/hello/v2"

على ما يبدو ، يتم ذلك بحيث يمكن استيراد إصدارات مختلفة من الحزم في تجميع واحد (انظر مشكلة التبعية الماسية ).

باختصار ، تتوقع Go أن تكون حذرًا للغاية عند تقديم الإصدارات الرئيسية.

استبدال الوحدات المستوردة


يمكنك تحديد الوحدة النمطية اللازمة للشوكة الخاصة بك أو حتى المسار المحلي للملف باستخدام التوجيه replace:

go mod edit -replace github.com/go-chi/chi=./packages/chi

نتيجة:

module github.com/you/hello
go 1.12
require github.com/go-chi/chi v4.0.2+incompatible
replace github.com/go-chi/chi => ./packages/chi

يمكنك حذف الخط يدويًا أو تشغيله:

go mod edit -dropreplace github.com/go-chi/chi

إدارة تبعية المشروع


تاريخيًا ، تم تخزين كل كود Go في مستودع أحادي عملاق واحد ، لأن هذه هي الطريقة التي تنظم بها Google قاعدة الرموز الخاصة بها ، وهذا يؤثر على تصميم اللغة.

وحدات Go هي خروج عن هذا النهج. لم تعد بحاجة إلى الاحتفاظ بجميع مشروعاتك $GOPATH.

ومع ذلك ، من الناحية الفنية ، لا تزال جميع التبعيات التي تم تنزيلها موجودة $GOPATH/pkg/mod. إذا كنت تستخدم حاويات Docker للتطوير المحلي ، فقد يكون هذا مشكلة ، حيث يتم تخزين التبعيات خارج المشروع. بشكل افتراضي ، فهي غير مرئية ببساطة في IDE الخاص بك.



عادةً لا يمثل هذا مشكلة للغات أخرى ، ولكن هذا ما واجهته لأول مرة عند العمل مع Go codebase.

لحسن الحظ ، هناك عدة طرق (غير موثقة) لحل هذه المشكلة.

الخيار 1. قم بتثبيت GOPATH داخل دليل المشروع الخاص بك.


للوهلة الأولى ، قد يبدو هذا غير بديهي ، ولكن إذا قمت بتشغيل Go من حاوية ، يمكنك تجاوز GOPATH بحيث تشير إلى دليل المشروع بحيث يمكن الوصول إلى الحزم من المضيف:

version: '3.7'

services:
  app:
    command: tail -f /dev/null
    image: golang:1.12.6-stretch
    environment:
      #        - /code/.go/pkg/mod
      - GOPATH=/code/.go
    ports:
      - 8000:8000
    volumes:
      - ./:/code:cached
    working_dir: /code

يجب أن تكون IDE المشهورة قادرة على تثبيت GOPATH على مستوى المشروع (مساحة العمل):



العيب الوحيد لهذا النهج هو عدم التفاعل مع وقت تشغيل Go على الكمبيوتر المضيف. يجب تنفيذ جميع أوامر Go داخل الحاوية.

الخيار 2: بيع تبعياتك


طريقة أخرى هي نسخ تبعيات مشروعك إلى مجلد vendor:

go mod vendor

تجدر الإشارة على الفور: لا نسمح لـ Go بتحميل المواد مباشرة إلى مجلد البائع: هذا غير ممكن مع الوحدات النمطية. نحن ببساطة نقوم بنسخ الحزم التي تم تنزيلها بالفعل.

بالإضافة إلى ذلك ، إذا قمت بإلغاء ربط تبعياتك ، كما هو موضح في المثال أعلاه ، فقم بمسح $GOPATH/pkg/modثم محاولة إضافة عدة تبعيات جديدة إلى مشروعك ، سترى ما يلي:

  1. سيقوم Go بإعادة إنشاء ذاكرة التخزين المؤقت للتنزيل لجميع حزم البرامج $GOPATH/pkg/mod/cache.
  2. سيتم نسخ جميع الوحدات المحملة إلى $GOPATH/pkg/mod.
  3. وأخيرًا ، سينسخ Go هذه الوحدات إلى vendorمجلد ، ويحذف الأمثلة والاختبارات وبعض الملفات الأخرى التي لا تعتمد عليها بشكل مباشر.

علاوة على ذلك ، هناك الكثير من الأشياء المفقودة في مجلد البائع الذي تم إنشاؤه حديثًا:



يبدو ملف Docker Compose النموذجي مثل هذا (لاحظ روابط الحجم):

version: '3.7'

services:
  app:
    command: tail -f /dev/null
    image: golang:1.12.6-stretch
    ports:
      - 8000:8000
    volumes:
     #    go,           
      - modules:/go/pkg/mod/cache
      - ./:/code:cached
    working_dir: /code 

volumes:
  modules:
    driver: local

يرجى ملاحظة أنني لا فكاهية مجلد البائع هذا في نظام التحكم في الإصدار أو لن أستخدمه في الإنتاج. هذا هو برنامج تطوير محلي صارم ، والذي يمكن العثور عليه عادة في بعض اللغات الأخرى.

ومع ذلك ، عندما قرأت تعليقات من بعض مشرفي Go وبعض العروض المتعلقة بالبيع الجزئي (CHE؟) ، لدي انطباع بأن هذه الميزة كانت في الأصل غير مخصصة لحالة المستخدم هذه. ساعدني

أحد المعلقين على reddit في إلقاء بعض الضوء على هذا:

عادة ما يقوم الأشخاص بتوزيع تبعياتهم لأسباب مثل الرغبة في الحصول على تجميعات ضيقة دون الوصول إلى الشبكة ، بالإضافة إلى توفر نسخة من التبعيات الجاهزة في حالة فشل github أو اختفاء المستودع ، وإمكانية مراجعة أسهل للتغيرات في التبعيات باستخدام أدوات VCS القياسية ، إلخ. .

نعم، انها لا تشبه أي شيء من حقيقة أنني قد تكون مهتمة.

وفقًا للأمر Go ، يمكنك بسهولة تمكين البيع عن طريق تعيين متغير بيئة GOFLAGS=-mod=vendor. أنا لا أنصح بذلك. سيؤدي استخدام العلامات إلى كسر ببساطة go getدون تقديم أي مزايا أخرى لسير عملك اليومي:



في الواقع ، المكان الوحيد الذي تحتاج إليه لتمكين البيع هو IDE الخاص بك:



بعد بعض التجربة والخطأ ، توصلت إلى الإجراء التالي لإضافة تبعيات المورد في هذا النهج.

الخطوة 1. المتطلبات


يمكنك طلب التبعية مع go get:

go get github.com/rs/zerolog@v1.14.3

الخطوة 2. الاستيراد


ثم قم باستيراده في مكان ما في التعليمات البرمجية:

import (
   _ "github.com/rs/zerolog"
)

الخطوة 3. البيع


أخيرًا ، أعد فتح تبعياتك:

go mod vendor

يوجد اقتراح معلق للسماح لبائع go mod بقبول قوالب وحدة نمطية معينة قد (أو لا) تحل بعض المشاكل المرتبطة بسير العمل هذا.

go mod vendorيتطلب بالفعل تلقائيًا عمليات الاستيراد الفائتة ، لذا فإن الخطوة 1 اختيارية في سير العمل هذا (إذا كنت لا تريد تحديد قيود الإصدار). ومع ذلك ، بدون الخطوة 2 ، لن تلتقط الحزمة التي تم تنزيلها.

يعمل هذا الأسلوب بشكل أفضل مع النظام المضيف ، ولكنه مربك إلى حد ما عندما يتعلق الأمر بتحرير تبعياتك.



أنا شخصياً أعتقد أن إعادة تعريف GOPATH هو نهج أنظف لأنه لا يضحي بالوظائف go get. ومع ذلك ، أردت أن أعرض كلا الإستراتيجيتين ، لأن مجلد البائع قد يكون مألوفًا أكثر للأشخاص القادمين من لغات أخرى ، مثل PHP و Ruby و Javascript وما إلى ذلك. كما ترى من الاحتيال الموضح في هذه المقالة ، هذا ليس خيارًا جيدًا بشكل خاص لـ Go.

تبعيات الأداة


قد نحتاج إلى تثبيت بعض الأدوات القائمة على Go التي لم يتم استيرادها ، ولكن يتم استخدامها كجزء من بيئة تطوير المشروع. مثال بسيط على هذه الأداة هو CompileDaemon ، والذي يمكنه مراقبة التعليمات البرمجية الخاصة بك للتغييرات وإعادة تشغيل التطبيق الخاص بك. النهج

الموصى به رسميًا هو إضافة tools.goملف (لا يهم الاسم) بالمحتوى التالي:

// +build tools
package tools
import (
_ "github.com/githubnemo/CompileDaemon"
)

  • // +build toolsيمنع القيد التجميعات العادية الخاصة بك من استيراد الأداة الخاصة بك بالفعل.
  • يسمح تعبير الاستيراد لأوامر go بكتابة معلومات إصدار أدواتك بدقة إلى ملف go.modالوحدة النمطية الخاص بك.

هذا كل شيء. آمل ألا تكون مرتبكًا كما كنت عندما بدأت باستخدام وحدات Go لأول مرة. يمكنك زيارة موقع Go Modules wiki لمزيد من التفاصيل.



احصل على الدورة.



All Articles