خادم ويب
لنختم ببرنامج Go كامل، خادم ويب. وهذا في الواقع نوع من خوادم الويب من نوع «إعادة». فجوجل توفّر خدمة على chart.apis.google.com تنسّق البيانات تلقائيًا في شكل رسوم بيانية ومخطّطات. غير أن استعمالها تفاعليًا صعب، لأن عليك وضع البيانات في عنوان URL كاستعلام. ويوفّر البرنامج هنا واجهة أجمل لشكل واحد من البيانات: فمعطى نصًّا قصيرًا، ينادي خادم الرسوم لتوليد رمز QR، وهو مصفوفة مربّعات تُرمِّز النص.
ويمكن التقاط تلك الصورة بكاميرا هاتفك وتفسيرها على أنها مثلًا عنوان URL، فيوفّرك كتابة العنوان في لوحة مفاتيح الهاتف الصغيرة.
وهذا هو البرنامج الكامل. ويأتي الشرح بعده.
package main
import (
"flag"
"html/template"
"log"
"net/http"
)
var addr = flag.String("addr", ":1718", "http service address") // Q=17, R=18
var templ = template.Must(template.New("qr").Parse(templateStr))
func main() {
flag.Parse()
http.Handle("/", http.HandlerFunc(QR))
err := http.ListenAndServe(*addr, nil)
if err != nil {
log.Fatal("ListenAndServe:", err)
}
}
func QR(w http.ResponseWriter, req *http.Request) {
templ.Execute(w, req.FormValue("s"))
}
const templateStr = `
<head>
<title>QR Link Generator</title>
</head>
<body>
{{if .}}
<img src="http://chart.apis.google.com/chart?chs=300x300&cht=qr&choe=UTF-8&chl={{.}}" />
<br>
{{.}}
<br>
<br>
{{end}}
<form action="/" name=f method="GET">
<input maxLength=1024 size=70 name=s value="" title="Text to QR Encode">
<input type=submit value="Show QR" name=qr>
</form>
</body>
`
الأجزاء حتى main يسهل تتبّعها. فالراية الواحدة تضبط منفذ HTTP افتراضيًا لخادمنا. أمّا متغيّر القالب templ فهنا يحدث السحر: فهو يبني قالب HTML سيُنفَّذ من الخادم لعرض الصفحة؛ والمزيد عنه بعد قليل.
وتحلّل دالة main الرايات، ثم — بالأليّة التي تحدثنا عنها أعلاه — تربط الدالة QR بالمسار الجذري للخادم. ثم يُنادى http.ListenAndServe لبدء الخادم، وهو يحظر ما دام الخادم يعمل.
أما QR فمجرّد ما تستقبل الطلب، الذي يحوي بيانات النموذج، وتُنفّذ القالب على البيانات الموجودة في قيمة النموذج المسمّاة s.
وحزمة القوالب html/template قويّة؛ وهذا البرنامج لا يلمس سوى قدرات منها. وبجوهرها، فإنها تعيد كتابة قطعة من نصّ HTML أثناء العمل باستبدال عناصر مشتقّة من عناصر بيانات تُمرَّر إلى templ.Execute، وهي هنا قيمة النموذج.
وداخل نصّ القالب (templateStr)، تشكّل القطع المحاطة بأقواس معقوفة مزدوجة إجراءات القالب. فالقطعة من {{if .}} إلى {{end}} تُنفَّذ فقط إن كانت قيمة عنصر البيانات الحالي، المسمّى . (dot)، غير فارغة. أي أنه عندما يكون النص فارغًا، تُحذف هذه القطعة من القالب.
أما المقطعان {{.}} فيقولان إن اعرض البيانات المقدَّمة للقالب — وهي سلسلة الاستعلام — في صفحة الويب. وتوفّر حزمة قوالب HTML تلقائيًا التهريب (escaping) المناسب، فيصبح النص آمنًا للعرض.
وبقية نصّ القالب ليست سوى HTML يُعرض عند تحميل الصفحة. وإن كان هذا الشرح سريعًا أكثر من اللازم، فراجع توثيق حزمة template لمناقشة أشمل.
وهكذاأمامك خادم ويب مفيد في بضعة أسطر من الشيفرة، مع نصّ HTML مبني على البيانات. وGo قوية بما يكفي لأن يحدث الكثير في بضعة أسطر.