gokayburuc.dev

GO ile QRcode Uygulaması

Proje Tanımı

Bu projede:

gibi sorulara birlikte cevap arayacağız.

Proje Amacı

Projemizin amacı, .txt uzantılı bir dosyada yer alan URL'lerimizi GO dili kullanarak toplu halde sisteme aktarmak ve ayrı ayrı QRCode Barkodları oluşturmaktır.

Proje Uygulaması

Proje Oluşturulması ve İlk Kurulumlar

Projeyi uygulayabilmek için ilk olarak bir GO projesi başlatıyoruz.

# bir proje klasörü oluşturun
md qrcode-projesi

# proje klasörüne change dir ile giris saglayın
cd qrcode-projesi/

# ismi dilediğiniz gibi değiştirebilirsiniz
go mod init projelerim/qrcode

Projemizi oluşturduktan sonra gerekli olan kütüphaneleri temin ederek devam ediyoruz. Bu projede kullanacağımız GO kütüphanesinin adı go-qrcode kütühanesidir.

skip2 qr-code

Oge Bilgisi Aciklama
Github Sayfası skip2/go-qrcode
Projeye Eklenme Yöntemi go get -u github.com/skip2/go-qrcode/...
Script'e Eklenme Yöntemi import qrcode "github.com/skip2/go-qrcode"
Resmi Dokumantasyon pkg.go.dev/skip2/qrcode

Şimdi temel bilgileri verdikten sonra terminalimize projeye eklenme yönteminde yazdığı şekilde go get -u github.com/skip2/go-qrcode/... yazıp Enter tuşuna basarak kütüphaneyi projemize dahil ediyoruz.

Şimdi dosyalarımızı oluşturmaya başlayalım.

Foldertree - Dosya Ağacı

Bir GO dosyasında modüllerde çalışacağımız için ilk olarak alt modülleri oluşturma ve çağırma pratiği yapmak adına aşağıdaki şekilde bir dosya ağacı foldertree oluşturuyoruz:

.
├── go.mod
├── go.sum
├── main.go
├── source.txt
├── qrgenerator
│   └── qrgenerate.go
├── README.md
└── textreader
    └── text-reader.go

Buradaki dosyaları kısaca açıklayalım:

source.txt

Bu dosyanın içerisine çıktısını almak istediğimiz URL linklerini ilave ediyoruz ve kaydediyoruz.

https://pkg.go.dev/github.com/skip2/go-qrcode#pkg-overview
https://www.qr-code-generator.com/
https://www.codewars.com/dashboard
https://rust-langturkiye.com/

qrgenerator.go

Öncelikle projemizin içinde qrgenerator/ isimli bir alt klasör oluşturalım. Burada paket ismi olarak qrgenerator ismini kullanacağız. Bu yazımın avantajı artık QRCode ile ilgili tüm işlemleri bu paket altında gerçekleştirebilmek ve main içerisinde tek satır bir kod yardımıyla tüm bu işlemleri gerçekleştirebilmektir. Büyük ölçekli projelerde paket package ve modül module mimarisi sayesinde kod hataları hızlı bir şekilde tespit edilebilmekte ve ekipler için net çalışma alanları belirlenebilmektedir. Bu yazıma alışmanızı öneriririm.

Kodumuz go dili altında package qrgenerator altında çalışacağı için script dosyamızın en başına bu ifadeyi ekliyoruz.

package qrgenerator

Şimdi ise projemize dahil edeceğimiz paketleri yazıyoruz. GO bunları yazım sırasında otomatik olarak projeye dahil etmektedir. Fakat biz yine de görmeniz açısından bunları belirtmeyi uygun buluyoruz.

import (
	"fmt" // temel format paketi
	"log" // logları yöneten paket
	"github.com/skip2/go-qrcode" // projemize dahil ettiğimiz paket
)

PNGCreator Fonksiyonu

Bu işlem de bittikten sonra şimdi QRCode için .png dosyaları oluşturan bir fonksiyon yazıyoruz:

func PNGCreator(fileno int, URL string) {
	png, err := qrcode.New(URL, qrcode.High)

	if err != nil {
		log.Fatal(err)
	}

	fileName := fmt.Sprintf("src/%v_qrcode.png", fileno)
	writeErr := png.WriteFile(256, fileName)

	if writeErr != nil {
		log.Fatal(writeErr)
	}

}

Burada öncelikle bir QRCode oluşturucu modeli yazıyoruz.

// qrcode.Medium , qrcode.High
png,err := qrcode.New(URL, qrcode.High)

qrcode.New() isimli fonksiyon []byte cinsinden bir adet çıktı ve bir error yani hata döndürür. Eğer dosya ile ilgili bir hata gerçekleşirse hata bloğundaki mesajı döndürür. Eğer hata mesajlarını almak istemiyorsanız bu kısma _ yazarak geçebilirsiniz.

if err != nil {
  log.Fatal(err)
}

Hata yönetimi için gerekli bloğu da yukarıdaki şekilde yazıyoruz.

fileName := fmt.Sprintf("src/%v_qrcode.png", fileno)

Bu kısımda ise fileName isimli bir değişkene fonksiyonda istediğimiz fileno isimli int tipindeki parametreyi dahil ederek bir dosya ismi oluşturan bir yapı yazıyoruz.

writeErr := png.WriteFile(256, fileName)

Burada işlemin en başında qrcode.New() ile oluşturduğumuz kodları dosyaya yazdırıyoruz. Burada işlem gerçekleşirken ekrana bir çıktı döndürmeyeceği için yalnızca işlem gerçekleşmediği anda error döndürecektir. İlgililer skip2/qr-code kısmında belirttiğimiz resmi dökümantasyondan go-qrcode kütüphanesinin çalışma mantığını inceleyebilirler.

Son olarak da kodumuza bir hata yöneticisi ekleyerek ilk fonksiyonumuzu kapatıyoruz.

	if writeErr != nil {
		log.Fatal(writeErr)
	}

Kodumuz bu haliyle, bir URL ve bir dosya numarası verildiğinde png oluşturacak halde kullanıma hazırdır. Şimdi süreçleri yönetecek yapıyı yazıyoruz.

QRGenerate Fonksiyonu

func QRGenerate(urllist []string) {

	for count, workingURL := range urllist {
		if len(workingURL) > 0 {
			fmt.Println(count, workingURL)
			PNGCreator(count, workingURL)
		}
	}
}

QRGenerate() isimli fonksiyonumuz urllist isimli bir array aldıktan sonra bu array'e ait URL'leri teker teker işleme tabi tutarak daha önce yazmış olduğumuz PNGCreator() isimli fonksiyonumuza parametre olarak girdi sağlıyor.

Bu yapıda for-range döngüsü kullandık:

for i,v := range arr {
  // code
}

// INFO : Parameters
// i => index number
// v => value
// arr => array

Döngüden anladığınız üzere bir index numarası ve diziye ait değeri birlikte döndürüyoruz.

Yazdığımız koda bir de ilave olarak satırın içerisinde bir öğe olup olmadığını denetleyen bir if-statement yani şayet ifadesi oluşturduk.

if len (workingURL) > 0 {
  //code
}

Son olarak da gelen değerleri parametre olarak PNGCreator() isimli fonksiyonumuza atadık.

PNGCreator(count,workingURL)

Kodumuzu topladığımızda da isimli fonksiyonu elde ettik.

func QRGenerate(urllist []string) {

	for count, workingURL := range urllist {
		if len(workingURL) > 0 {
			fmt.Println(count, workingURL)
			PNGCreator(count, workingURL)
		}
	}
}

qrgenerator.go Scripti

Bütün işlemleri tamamladıktan sonra qrgenerator.go isimli dosyamızın son hali aşağıdaki gibi olacaktır.

package qrgenerator

import (
	"fmt"
	"log"

	"github.com/skip2/go-qrcode"
)

func QRGenerate(urllist []string) {
	// reads urllist

	for count, workingURL := range urllist {

		if len(workingURL) > 0 {
			fmt.Println(count, workingURL)
			PNGCreator(count, workingURL)
		}
	}
}

func PNGCreator(fileno int, URL string) {
	png, err := qrcode.New(URL, qrcode.High)

	if err != nil {
		log.Fatal(err)
	}

	fileName := fmt.Sprintf("src/%v_qrcode.png", fileno)
	writeErr := png.WriteFile(256, fileName)

	if writeErr != nil {
		log.Fatal(writeErr)
	}

}

Şimdi de metin okuma faaliyetlerine geçiyoruz.

text-reader.go

Öncelikle textreader/ klasörü içinde text-reader.go isimli bir dosya oluşturalım. Şimdi oluşturduğumuz bu dosyanın içerisine veri okuyan bir ReadData() fonksiyonu yazalım.

func ReadData(fpath string) []string {
	file, err := os.Open(fpath) // open a file with os library

	defer file.Close() // close file  at the end of the process

	if err != nil {
		log.Fatal(err)
	}

	readed, _ := io.ReadAll(file)

	myarray := strings.Split(string(readed), "\n")
	return myarray
}

HATIRLATMA: URL linklerimizi source.txt isimli dosyamıza yapıştırdıktan sonra fonksiyonları çalıştıracağız.

file,err := os.Open(fpath)

Burada os.Open() ile dosya yolu fpath olacak şekilde bir bir dosya açtık. Bu fonksiyon []byte cinsinden bir değer ve err şeklinde bir hata döndür. Hata kontrol ifadesini de ekledik.

if err != nil {
	log.Fatal(err)
}

Açtığımız file isimli dosya hafızada yer kaplamaması için işlem bitinde kapanacak şekilde konumlandırıyoruz.

defer file.Close()

Şimdi ise byte olarak okunan değeri io.ReadAll() yardımıyla insan tarafından okunabilir hale getiriyoruz.

readed, err := io.ReadAll(file)

io.ReadAll() okunan veri ve bir hata döndürür. Okunan veriyi de string formatına getireceğiz.

myarray := strings.Split(string(readed), "\n")

Yukarıdaki ifade okunan veriyi bir array haline getirir. strings.Split() ile her yeni satırı \n bir ayraç olarak kullanarak bir array oluşturuyoruz.

Kodumuzu bir araya derlediğimizde aşağıdaki şekilde bir script dosyası elde ediyoruz.

package textreader

import (
	"io"
	"log"
	"os"
	"strings"
)

// PASSED : read from a txt file
func ReadData(fpath string) []string {
	file, err := os.Open(fpath) // open a file with os library

	defer file.Close() // close file  at the end of the process

	if err != nil {
		log.Fatal(err)
	}

	readed, err := io.ReadAll(file)

	// PASSED : convert string into array
	myarray := strings.Split(string(readed), "\n")
	return myarray
}

main.go

Şimdi ise son kısım olan main.go dosyasının içeriğini yazıyoruz.

package main

import (
	"gokayburuc/qrcode/qrgenerator"
	"gokayburuc/qrcode/textreader"
)

func main() {

  qrgenerator.VCFGenerator()

}

func BulkQRCode() {
	var filepath string = "source.txt"
	urllist := textreader.ReadData(filepath)
	qrgenerator.QRGenerate(urllist)
}

Burada temel fonksiyonumuz BulkQRCode() isimli fonksiyondur.

func BulkQRCode() {
	var filepath string = "source.txt"
	urllist := textreader.ReadData(filepath)
	qrgenerator.QRGenerate(urllist)
}

source.txt isimli dosyanın veri yolunu textreader.ReadData(filepath) isimli değişkene filepath olarak atıyoruz. qrgenerate.QRGenerate(urllist) ile de elde ettiğimiz array ifadesindeki değerleri QRCode ifadelerine dönüştürüyoruz.

import (
	"gokayburuc/qrcode/qrgenerator"
	"gokayburuc/qrcode/textreader"
)

Burada benim projemdeki veri yolları import edilmiştir. Sizin projenizde veri yolları projenize verdiğiniz isme göre güncellenecektir.

Buraya kadar yaptıklarımızı ve kodun çalışır halini görmek için aşağıdaki videoyu izleyin :

Yeni yazılarda görüşmek üzere...