
مرحبا بالجميع! هناك الكثير من المقالات حول GraphQL على هبر ، ولكن بعد أن تدربت عليها ، وجدت أنها تتخطى جميعًا لغة رائعة مثل Go. اليوم سأحاول تصحيح سوء الفهم هذا. للقيام بذلك ، سنكتب API على Go باستخدام GraphQL.
باختصار: GraphQL هي لغة استعلام لإنشاء واجهة برمجة تطبيقات تصف في أي شكل تطلب وتعرض البيانات (معلومات أكثر تفصيلاً عن المورد الرسم البياني الرسمى gq.gubub.io وعن المحور )
يمكنك القول أن GraphQL أو REST أفضل هنا.
سيكون لدينا API الكلاسيكي: CRUD (إنشاء ، قراءة ، تحديث ، حذف) إضافة المنتجات وتلقيها وتحريرها وحذفها في المتجر عبر الإنترنت.
على جانب الخادم ، سنستخدم التنفيذ الجاهز لـ Graphql-go
تحتاج أولاً إلى تنزيل graphql-go ، ويمكن القيام بذلك باستخدام الأمر
go get github.com/graphql-go/graphql
بعد ذلك ، نصف هيكل المنتج (في شكل مبسط)
type Product struct { ID int64 `json:"id"` Name string `json:"name"` Info string `json:"info,omitempty"` Price float64 `json:"price"` }
ID
- ID
الفريد ، Name
- الاسم ، Info
- Info
المنتج ، Price
- السعر
أول شيء يجب فعله هو استدعاء طريقة Do
، التي تقبل مخطط البيانات ومعلمات الاستعلام كمعلمات إدخال. وستعيد لنا البيانات الناتجة (لمزيد من الإرسال إلى العميل)
result := graphql.Do(graphql.Params{ Schema: schema, RequestString: query, })
كود كامل func executeQuery(query string, schema graphql.Schema) *graphql.Result { result := graphql.Do(graphql.Params{ Schema: schema, RequestString: query, }) if len(result.Errors) > 0 { fmt.Printf("errors: %v", result.Errors) } return result } func main() { http.HandleFunc("/product", func(w http.ResponseWriter, r *http.Request) { result := executeQuery(r.URL.Query().Get("query"), schema) json.NewEncoder(w).Encode(result) }) http.ListenAndServe(":8080", nil) }
Schema
- Schema
البيانات ، RequestString
- قيمة معلمة سلسلة الاستعلام ، في حالتنا ، قيمة query
مخطط
يقبل المخطط نوعين من بيانات الجذر: Query
- البيانات غير القابلة للتغيير ، Mutation
- البيانات القابلة للتغيير
var schema, _ = graphql.NewSchema( graphql.SchemaConfig{ Query: queryType, Mutation: mutationType, }, )
الاستعلام
يستخدم Query
لقراءة البيانات (وقراءتها فقط). باستخدام Query
نحدد البيانات التي يجب أن يعرضها الخادم.
سنكتب تنفيذًا لنوع بيانات Query
، في حالتنا ، سيحتوي على حقول تحتوي على معلومات حول منتج واحد (منتج) وقائمة سلع (قائمة)
var queryType = graphql.NewObject( graphql.ObjectConfig{ Name: "Query", Fields: graphql.Fields{ "product": &graphql.Field{ Type: productType, Description: "Get product by id",
يحتوي نوع queryType على Name
Fields
المطلوبة ، بالإضافة إلى Description
الاختياري (المستخدم للوثائق)
في المقابل ، يحتوي حقل Fields
أيضًا على حقل Type
المطلوب وحقول Args
و Resolve
Description
الاختيارية
Args (وسيطات)
الوسيطات - قائمة بالمعلمات المنقولة من العميل إلى الخادم وتؤثر على نتيجة البيانات التي تم إرجاعها. ترتبط الوسيطات بحقل معين. ويمكن تمرير الحجج في كل من Query
Mutation
.
?query={product(id:1){name,info,price}}
في هذه الحالة ، تشير وسيطة id
لحقل product
بقيمة 1 إلى ضرورة إعادة المنتج id
المحدد.
بالنسبة إلى list
يتم حذف الوسيطات ، ولكن في تطبيق حقيقي يمكن أن تكون ، على سبيل المثال: limit
offset
.
حل (الاعتراف)
كل منطق العمل مع البيانات (على سبيل المثال ، استعلامات قاعدة البيانات والمعالجة والتصفية) موجود في أدوات التعرف ، وهم الذين يعيدون البيانات التي سيتم إرسالها إلى العميل كاستجابة للطلب.
اكتب
يستخدم GraphQL نظام نوعه لوصف البيانات. يمكنك استخدام كل من الأنواع الأساسية String
و Int
و Float
و Boolean
والأنواع الخاصة بك (المخصصة). على سبيل المثال ، سنحتاج إلى نوع Product
مخصص ، والذي سيصف جميع خصائص المنتج
var productType = graphql.NewObject( graphql.ObjectConfig{ Name: "Product", Fields: graphql.Fields{ "id": &graphql.Field{ Type: graphql.Int, }, "name": &graphql.Field{ Type: graphql.String, }, "info": &graphql.Field{ Type: graphql.String, }, "price": &graphql.Field{ Type: graphql.Float, }, }, }, )
بالنسبة لكل حقل ، يتم تحديد النوع الأساسي ، في هذه الحالة ، graphql.String
، graphql.Float
، graphql.Float
.
عدد الحقول المتداخلة غير محدود ، لذا يمكنك تنفيذ نظام رسم بياني بأي مستوى.
طفرة
الطفرات هي هذه البيانات القابلة للتغيير ، والتي تشمل: الجمع والتحرير والحذف. خلاف ذلك ، فإن الطفرات تشبه إلى حد كبير الاستعلامات العادية: فهي أيضًا تأخذ حجج Args
Resolve
البيانات كرد على الاستعلام.
دعونا نكتب طفرات لمنتجاتنا. var mutationType = graphql.NewObject(graphql.ObjectConfig{ Name: "Mutation", Fields: graphql.Fields{ "create": &graphql.Field{ Type: productType, Description: "Create new product", Args: graphql.FieldConfigArgument{ "name": &graphql.ArgumentConfig{ Type: graphql.NewNonNull(graphql.String),
كلها مشابهة ل queryType
. لا يوجد سوى graphql.NewNonNull(graphql.Int)
صغير لنوع الميزة واحد. graphql.NewNonNull(graphql.Int)
، والذي يخبرنا أن هذا الحقل لا يمكن أن يكون فارغًا (مشابه لـ NOT NULL
في MySQL)
هذا كل شيء. الآن لدينا واجهة برمجة تطبيقات Go CRUD بسيطة للعمل مع السلع. لم نستخدم قاعدة البيانات لهذا المثال ، لكننا نظرنا في كيفية إنشاء نموذج بيانات والتعامل معها باستخدام الطفرات.
أمثلة
إذا قمت بتنزيل المصدر من خلال
go get github.com/graphql-go/graphql
فقط اذهب إلى الدليل بمثال
cd examples/crud
وتشغيل التطبيق
go run main.go
يمكنك استخدام الاستعلامات التالية:
الحصول على المنتج بالمعرف
http://localhost:8080/product?query={product(id:1){name,info,price}}
الحصول على قائمة المنتجات
http://localhost:8080/product?query={list{id,name,info,price}}
إضافة منتج جديد
http://localhost:8080/product?query=mutation+_{create(name:"Tequila",info:"Strong alcoholic beverage",price:999){id,name,info,price}}
تحرير المنتج
http://localhost:8080/product?query=mutation+_{update(id:1,price:195){id,name,info,price}}
إزالة منتج بمعرف
http://localhost:8080/product?query=mutation+_{delete(id:1){id,name,info,price}}
إذا كنت تستخدم REST ، انتبه إلى GraphQL كبديل محتمل. نعم ، للوهلة الأولى ، يبدو الأمر أكثر صعوبة ، لكن الأمر يستحق البدء ، وفي غضون يومين سوف تتقن هذه التكنولوجيا. على الأقل سيكون مفيدا.