{"id":42123,"date":"2026-05-27T21:07:16","date_gmt":"2026-05-27T18:07:16","guid":{"rendered":"https:\/\/fatihsoysal.com\/blog\/go-dilinde-ilk-linterinizi-nasil-olusturursunuz\/"},"modified":"2026-05-27T21:07:48","modified_gmt":"2026-05-27T18:07:48","slug":"go-dilinde-ilk-linterinizi-nasil-olusturursunuz","status":"publish","type":"post","link":"https:\/\/fatihsoysal.com\/blog\/go-dilinde-ilk-linterinizi-nasil-olusturursunuz\/","title":{"rendered":"Go Dilinde \u0130lk Linter&#8217;\u0131n\u0131z\u0131 Nas\u0131l Olu\u015fturursunuz?"},"content":{"rendered":"<h2>Go Dilinde \u0130lk Linter&#8217;\u0131n\u0131z\u0131 Nas\u0131l Olu\u015fturursunuz?<\/h2>\n<p>Yaz\u0131l\u0131m geli\u015ftirme s\u00fcrecinde kod kalitesi, tutarl\u0131l\u0131k ve hata tespiti her zaman \u00f6ncelikli konular olmu\u015ftur. Peki, kodunuzdaki potansiyel sorunlar\u0131 daha derleyiciye gitmeden, hatta kod incelemesine (code review) bile gelmeden otomatik olarak yakalamak istemez misiniz? \u0130\u015fte tam da bu noktada linter&#8217;lar devreye giriyor. Go dilinin sundu\u011fu g\u00fc\u00e7l\u00fc statik analiz ara\u00e7lar\u0131 ve esnek yap\u0131s\u0131 sayesinde, kendi \u00f6zel linter&#8217;\u0131n\u0131z\u0131 olu\u015fturmak sand\u0131\u011f\u0131n\u0131zdan \u00e7ok daha kolay. Bu makalede, Go dilinde s\u0131f\u0131rdan bir linter geli\u015ftirmek i\u00e7in ad\u0131m ad\u0131m bir yolculu\u011fa \u00e7\u0131kacak, temel kavramlardan ileri d\u00fczey ipu\u00e7lar\u0131na kadar her \u015feyi ke\u015ffedece\u011fiz. B\u00f6ylece, ekip standartlar\u0131n\u0131za uygun, daha temiz ve hatas\u0131z kod yazma al\u0131\u015fkanl\u0131\u011f\u0131 kazanman\u0131za yard\u0131mc\u0131 olacak g\u00fc\u00e7l\u00fc bir araca sahip olacaks\u0131n\u0131z.<\/p>\n<h2>Neden Bir Linter&#8217;a \u0130htiyac\u0131m\u0131z Var? Kod Kalitesini Otomatikle\u015ftirme Sanat\u0131<\/h2>\n<p>Her geli\u015ftirici, kariyerinin bir noktas\u0131nda k\u00f6t\u00fc yaz\u0131lm\u0131\u015f, okunmas\u0131 zor veya gizli hatalar bar\u0131nd\u0131ran kodlarla kar\u015f\u0131la\u015fm\u0131\u015ft\u0131r. Bu t\u00fcr kodlar, projenin bak\u0131m\u0131n\u0131 zorla\u015ft\u0131r\u0131r, yeni \u00f6zellik eklemeyi yava\u015flat\u0131r ve uzun vadede maliyetleri art\u0131r\u0131r. Manuel kod incelemeleri (code review) bu sorunlar\u0131 tespit etmede etkili olsa da, insan hatas\u0131na a\u00e7\u0131k ve zaman al\u0131c\u0131 bir s\u00fcre\u00e7tir. Ayr\u0131ca, her ekip \u00fcyesinin ayn\u0131 kodlama standartlar\u0131na uymas\u0131n\u0131 sa\u011flamak da s\u00fcrekli bir \u00e7aba gerektirir. \u0130\u015fte bu noktada linter&#8217;lar, geli\u015ftirme s\u00fcrecinin vazge\u00e7ilmez bir par\u00e7as\u0131 haline gelir.<\/p>\n<p>Bir linter (genellikle &#8220;lint&#8221; olarak da bilinir), kaynak kodunuzu statik olarak analiz eden bir ara\u00e7t\u0131r. Yani, kodu \u00e7al\u0131\u015ft\u0131rmadan \u00f6nce, olas\u0131 hatalar\u0131, stil ihlallerini, \u015f\u00fcpheli yap\u0131lar\u0131 veya belirli kurallara uymayan durumlar\u0131 tespit eder. Go ekosistemi, bu konuda olduk\u00e7a zengin bir yap\u0131ya sahiptir. Go&#8217;nun kendisi, <code>go vet<\/code> gibi temel statik analiz ara\u00e7lar\u0131yla gelir ve topluluk taraf\u0131ndan geli\u015ftirilen bir\u00e7ok g\u00fc\u00e7l\u00fc linter (\u00f6rne\u011fin <code>golangci-lint<\/code>) mevcuttur. Ancak bazen, standart linter&#8217;lar\u0131n kapsamad\u0131\u011f\u0131, projenize veya ekibinize \u00f6zel kurallara ihtiyac\u0131n\u0131z olabilir. \u00d6rne\u011fin, belirli bir k\u00fct\u00fcphanenin kullan\u0131m\u0131n\u0131 k\u0131s\u0131tlamak, belirli bir fonksiyon adland\u0131rma kural\u0131n\u0131 zorunlu k\u0131lmak veya &#8220;magic number&#8221; (do\u011frudan kod i\u00e7ine yaz\u0131lm\u0131\u015f, anlam\u0131 belirsiz sabit say\u0131lar) kullan\u0131m\u0131n\u0131 engellemek isteyebilirsiniz. Kendi linter&#8217;\u0131n\u0131z\u0131 olu\u015fturmak, size bu \u00f6zel ihtiya\u00e7lar\u0131 kar\u015f\u0131lama esnekli\u011fi sunar.<\/p>\n<p>Kendi linter&#8217;\u0131n\u0131z\u0131 geli\u015ftirmenin faydalar\u0131 saymakla bitmez: \u00d6ncelikle, kod taban\u0131n\u0131zda tutarl\u0131l\u0131\u011f\u0131 art\u0131r\u0131rs\u0131n\u0131z. Herkes ayn\u0131 kurallara uydu\u011fu i\u00e7in, farkl\u0131 geli\u015ftiriciler taraf\u0131ndan yaz\u0131lm\u0131\u015f kodlar bile benzer bir yap\u0131ya sahip olur. \u0130kinci olarak, potansiyel hatalar\u0131 erken a\u015famada yakalayarak geli\u015ftirme d\u00f6ng\u00fcs\u00fcn\u00fc h\u0131zland\u0131r\u0131rs\u0131n\u0131z. Derleme zaman\u0131 hatalar\u0131ndan \u00f6nce linter hatalar\u0131n\u0131 d\u00fczeltmek, \u00e7ok daha az maliyetlidir. \u00dc\u00e7\u00fcnc\u00fc olarak, kod inceleme s\u00fcre\u00e7lerini daha verimli hale getirirsiniz. Linter&#8217;\u0131n otomatik olarak buldu\u011fu sorunlarla u\u011fra\u015fmak yerine, inceleyiciler daha \u00e7ok mimari kararlara ve i\u015f mant\u0131\u011f\u0131na odaklanabilirler. Son olarak, yeni ekip \u00fcyelerinin projenin kodlama standartlar\u0131na daha h\u0131zl\u0131 adapte olmas\u0131na yard\u0131mc\u0131 olursunuz. Linter, bir nevi otomatik bir mentor g\u00f6revi g\u00f6rerek do\u011fru pratikleri te\u015fvik eder. Go&#8217;nun g\u00fc\u00e7l\u00fc <code>go\/ast<\/code> (Abstract Syntax Tree &#8211; Soyut S\u00f6zdizimi A\u011fac\u0131) ve <code>golang.org\/x\/tools\/go\/analysis<\/code> paketleri sayesinde, bu s\u00fcreci olduk\u00e7a kolay ve keyifli bir hale getirebiliriz.<\/p>\n<h2>Linter Nedir ve Go&#8217;da Nas\u0131l \u00c7al\u0131\u015f\u0131r? Soyut S\u00f6zdizimi A\u011fa\u00e7lar\u0131na Giri\u015f<\/h2>\n<p>Bir linter&#8217;\u0131n kalbinde, kaynak kodunuzu anlama yetene\u011fi yatar. Bilgisayarlar, yazd\u0131\u011f\u0131m\u0131z d\u00fcz metin kodu do\u011frudan yorumlayamazlar. Bunun yerine, bu kodu bir dizi a\u015famadan ge\u00e7irerek anlaml\u0131 bir yap\u0131ya d\u00f6n\u00fc\u015ft\u00fcr\u00fcrler. Bu a\u015famalardan biri de &#8220;parsing&#8221; (ayr\u0131\u015ft\u0131rma) i\u015flemidir. Ayr\u0131\u015ft\u0131rma sonucunda, kodun yap\u0131sal temsilini g\u00f6steren bir Soyut S\u00f6zdizimi A\u011fac\u0131 (Abstract Syntax Tree &#8211; AST) elde edilir. AST, program\u0131n hiyerar\u015fik yap\u0131s\u0131n\u0131 d\u00fc\u011f\u00fcmler ve dallar arac\u0131l\u0131\u011f\u0131yla g\u00f6steren bir veri yap\u0131s\u0131d\u0131r. Her bir d\u00fc\u011f\u00fcm, kodun bir b\u00f6l\u00fcm\u00fcn\u00fc (\u00f6rne\u011fin, bir de\u011fi\u015fken bildirimi, bir fonksiyon \u00e7a\u011fr\u0131s\u0131, bir if ifadesi veya bir operat\u00f6r) temsil eder.<\/p>\n<p>Go dilinde, AST ile \u00e7al\u0131\u015fmak i\u00e7in olduk\u00e7a g\u00fc\u00e7l\u00fc yerle\u015fik paketler bulunur. <code>go\/parser<\/code> paketi, Go kaynak kodunu ayr\u0131\u015ft\u0131rarak bir AST olu\u015fturman\u0131z\u0131 sa\u011flar. <code>go\/ast<\/code> paketi ise, bu AST&#8217;yi temsil eden veri yap\u0131lar\u0131n\u0131 ve a\u011fa\u00e7 \u00fczerinde gezinmek i\u00e7in yard\u0131mc\u0131 fonksiyonlar\u0131 i\u00e7erir. Linter&#8217;lar tam da bu AST \u00fczerinde \u00e7al\u0131\u015f\u0131r. Bir linter, kaynak kodunu bir AST&#8217;ye d\u00f6n\u00fc\u015ft\u00fcrd\u00fckten sonra, bu a\u011fac\u0131 dola\u015f\u0131r ve belirli desenleri, yap\u0131lar\u0131 veya kurallar\u0131 arar. \u00d6rne\u011fin, bir linter, bir fonksiyonun \u00e7ok uzun olup olmad\u0131\u011f\u0131n\u0131, belirli bir de\u011fi\u015fkenin kullan\u0131lmad\u0131\u011f\u0131n\u0131 veya bir &#8220;import&#8221; ifadesinin yanl\u0131\u015f yerde olup olmad\u0131\u011f\u0131n\u0131 kontrol etmek i\u00e7in AST&#8217;yi kullanabilir.<\/p>\n<p>Go&#8217;nun <code>go\/analysis<\/code> framework&#8217;\u00fc (<code>golang.org\/x\/tools\/go\/analysis<\/code> paketi alt\u0131nda bulunur), linter yazmay\u0131 standartla\u015ft\u0131ran ve kolayla\u015ft\u0131ran g\u00fc\u00e7l\u00fc bir yap\u0131d\u0131r. Bu framework, bir linter&#8217;\u0131 bir <code>analysis.Analyzer<\/code> olarak tan\u0131mlaman\u0131z\u0131 sa\u011flar. Bir <code>Analyzer<\/code>, kendi ba\u015f\u0131na bir analiz birimi olup, belirli bir kontrol\u00fc veya kural\u0131 uygular. Bu framework, farkl\u0131 linter&#8217;lar\u0131n bir araya getirilerek tek bir ara\u00e7 alt\u0131nda \u00e7al\u0131\u015ft\u0131r\u0131lmas\u0131na olanak tan\u0131r, t\u0131pk\u0131 <code>golangci-lint<\/code>&#8216;in yapt\u0131\u011f\u0131 gibi. Her bir <code>Analyzer<\/code>, <code>Run<\/code> ad\u0131nda bir metot i\u00e7erir. Bu metot, kendisine bir <code>analysis.Pass<\/code> nesnesi alarak \u00e7al\u0131\u015f\u0131r. <code>analysis.Pass<\/code> nesnesi, analiz edilen paketin AST&#8217;si, dosya k\u00fcmeleri, tip bilgileri ve di\u011fer ba\u011flam bilgilerini i\u00e7erir. Linter&#8217;\u0131n\u0131z, bu <code>Pass<\/code> nesnesini kullanarak AST \u00fczerinde gezinebilir ve buldu\u011fu sorunlar\u0131 <code>pass.Reportf<\/code> fonksiyonu arac\u0131l\u0131\u011f\u0131yla raporlayabilir.<\/p>\n<p>K\u0131sacas\u0131, Go&#8217;da bir linter olu\u015fturmak i\u00e7in \u015fu ad\u0131mlar\u0131 izleyece\u011fiz: \u00d6ncelikle, <code>go\/parser<\/code> kullanarak kaynak kodu bir AST&#8217;ye d\u00f6n\u00fc\u015ft\u00fcrece\u011fiz. Ard\u0131ndan, <code>go\/ast<\/code> paketindeki <code>ast.Inspect<\/code> gibi fonksiyonlar\u0131 kullanarak bu AST \u00fczerinde gezinece\u011fiz. Son olarak, <code>golang.org\/x\/tools\/go\/analysis<\/code> framework&#8217;\u00fcn\u00fc kullanarak kendi analiz\u00f6r\u00fcm\u00fcz\u00fc tan\u0131mlayacak ve buldu\u011fumuz sorunlar\u0131 bu framework&#8217;\u00fcn raporlama mekanizmas\u0131yla kullan\u0131c\u0131lara sunaca\u011f\u0131z. Bu yap\u0131, hem basit hem de karma\u015f\u0131k linter kurallar\u0131 geli\u015ftirmek i\u00e7in olduk\u00e7a esnek ve g\u00fc\u00e7l\u00fc bir temel sa\u011flar.<\/p>\n<h2>Temel Bir Go Linter&#8217;\u0131 Olu\u015fturmaya Ba\u015flang\u0131\u00e7: Proje Yap\u0131s\u0131 ve \u0130lk Ad\u0131mlar<\/h2>\n<p>Kendi Go linter&#8217;\u0131m\u0131z\u0131 olu\u015fturmaya ba\u015flamadan \u00f6nce, basit bir proje yap\u0131s\u0131 kural\u0131m ve gerekli Go mod\u00fcllerini tan\u0131mlayal\u0131m. Bu, projemizi d\u00fczenli tutmam\u0131za ve ba\u011f\u0131ml\u0131l\u0131klar\u0131 y\u00f6netmemize yard\u0131mc\u0131 olacakt\u0131r. Linter&#8217;\u0131m\u0131z\u0131, <code>cmd<\/code> dizini alt\u0131nda \u00e7al\u0131\u015ft\u0131r\u0131labilir bir uygulama olarak, ana analiz mant\u0131\u011f\u0131n\u0131 ise ayr\u0131 bir pakette tutacak \u015fekilde tasarlayaca\u011f\u0131z. Bu ayr\u0131m, linter&#8217;\u0131m\u0131z\u0131 hem ba\u011f\u0131ms\u0131z bir ara\u00e7 olarak \u00e7al\u0131\u015ft\u0131rmam\u0131za hem de ba\u015fka ara\u00e7lar (\u00f6rne\u011fin <code>golangci-lint<\/code>) taraf\u0131ndan bir k\u00fct\u00fcphane olarak kullan\u0131lmas\u0131na olanak tan\u0131r.<\/p>\n<p>\u0130lk olarak, projemiz i\u00e7in bir dizin olu\u015ftural\u0131m ve Go mod\u00fcl\u00fcn\u00fc ba\u015flatal\u0131m:<\/p>\n<div class=\"code-container\">\n<pre><code>\nmkdir mylinter\ncd mylinter\ngo mod init github.com\/kullaniciadi\/mylinter\n  <\/code><\/pre>\n<\/div>\n<p>\u015eimdi, linter&#8217;\u0131m\u0131z\u0131n ana mant\u0131\u011f\u0131n\u0131 bar\u0131nd\u0131racak paketi ve \u00e7al\u0131\u015ft\u0131r\u0131labilir dosyas\u0131n\u0131 olu\u015ftural\u0131m:<\/p>\n<div class=\"code-container\">\n<pre><code>\nmkdir internal\/mylinter\nmkdir cmd\/mylinter\ntouch internal\/mylinter\/mylinter.go\ntouch cmd\/mylinter\/main.go\n  <\/code><\/pre>\n<\/div>\n<p>Proje yap\u0131m\u0131z \u015fu \u015fekilde g\u00f6r\u00fcnecektir:<\/p>\n<div class=\"code-container\">\n<pre><code>\nmylinter\/\n\u251c\u2500\u2500 cmd\/\n\u2502   \u2514\u2500\u2500 mylinter\/\n\u2502       \u2514\u2500\u2500 main.go\n\u2514\u2500\u2500 internal\/\n    \u2514\u2500\u2500 mylinter\/\n        \u2514\u2500\u2500 mylinter.go\n  <\/code><\/pre>\n<\/div>\n<p>\u015eimdi, <code>internal\/mylinter\/mylinter.go<\/code> dosyam\u0131zda linter&#8217;\u0131m\u0131z\u0131n \u00e7ekirde\u011fini tan\u0131mlayal\u0131m. Bu dosya, <code>golang.org\/x\/tools\/go\/analysis<\/code> framework&#8217;\u00fcnden <code>analysis.Analyzer<\/code> yap\u0131s\u0131n\u0131 kullanarak linter&#8217;\u0131m\u0131z\u0131 tan\u0131mlayacak. \u0130lk linter kural\u0131m\u0131z olarak, \u00e7ok basit bir \u015fey yapal\u0131m: belirli bir paketin (\u00f6rne\u011fin, &#8220;fmt&#8221; paketi) do\u011frudan kullan\u0131m\u0131n\u0131 engellemeye \u00e7al\u0131\u015fal\u0131m. Bu, genellikle bir projenin kendi loglama veya hata y\u00f6netimi k\u00fct\u00fcphanelerini kullanmas\u0131n\u0131 te\u015fvik etmek i\u00e7in yap\u0131l\u0131r.<\/p>\n<div class=\"code-container\">\n<pre><code>\n\/\/ internal\/mylinter\/mylinter.go\npackage mylinter\n\nimport (\n\t\"go\/ast\"\n\t\"golang.org\/x\/tools\/go\/analysis\"\n\t\"golang.org\/x\/tools\/go\/analysis\/passes\/inspect\"\n)\n\n\/\/ Analyzer, linter'\u0131m\u0131z\u0131n ana tan\u0131m\u0131d\u0131r.\nvar Analyzer = &analysis.Analyzer{\n\tName: \"noFmtImport\", \/\/ Linter'\u0131m\u0131z\u0131n ad\u0131\n\tDoc:  \"fmt paketinin do\u011frudan kullan\u0131m\u0131n\u0131 engeller.\", \/\/ Linter'\u0131m\u0131z\u0131n a\u00e7\u0131klamas\u0131\n\tRun:  run, \/\/ Linter'\u0131n \u00e7al\u0131\u015ft\u0131r\u0131lacak fonksiyonu\n\tRequires: []*analysis.Analyzer{\n\t\tinspect.Analyzer, \/\/ AST \u00fczerinde gezinmek i\u00e7in gerekli olan analiz\u00f6r\n\t},\n}\n\nfunc run(pass *analysis.Pass) (interface{}, error) {\n\t\/\/ inspect.Analyzer taraf\u0131ndan sa\u011flanan AST inspector'\u0131 alal\u0131m.\n\t\/\/ Bu, AST \u00fczerinde kolayca gezinmemizi sa\u011flar.\n\tinspector := pass.ResultOf[inspect.Analyzer].(*ast.Inspector)\n\n\t\/\/ Sadece dosya seviyesindeki import bildirimlerini kontrol etmek i\u00e7in filtre uygulayal\u0131m.\n\tnodeFilter := []ast.Node{\n\t\t(*ast.ImportSpec)(nil),\n\t}\n\n\tinspector.Preorder(nodeFilter, func(n ast.Node) {\n\t\timportSpec := n.(*ast.ImportSpec)\n\t\t\/\/ Import yolunu t\u0131rnak i\u015faretlerinden ar\u0131nd\u0131rarak alal\u0131m.\n\t\timportPath := importSpec.Path.Value\n\t\tif importPath == <code>&quot;fmt&quot;<\/code> {\n\t\t\t\/\/ E\u011fer \"fmt\" paketi import edilmi\u015fse, bir hata raporlayal\u0131m.\n\t\t\tpass.Reportf(importSpec.Pos(), \"fmt paketi kullan\u0131lamaz, l\u00fctfen \u00f6zel loglama paketinizi kullan\u0131n.\")\n\t\t}\n\t})\n\n\treturn nil, nil\n}\n  <\/code><\/pre>\n<\/div>\n<p>Yukar\u0131daki kodda, <code>analysis.Analyzer<\/code> yap\u0131s\u0131n\u0131 tan\u0131mlad\u0131k. <code>Name<\/code> ve <code>Doc<\/code> alanlar\u0131 linter&#8217;\u0131m\u0131z\u0131 tan\u0131t\u0131r. <code>Run<\/code> alan\u0131, linter&#8217;\u0131n ana mant\u0131\u011f\u0131n\u0131 i\u00e7eren fonksiyondur. <code>Requires<\/code> alan\u0131 ise, bu linter&#8217;\u0131n \u00e7al\u0131\u015fabilmesi i\u00e7in ba\u015fka hangi analiz\u00f6rlere ihtiya\u00e7 duydu\u011funu belirtir. Burada <code>inspect.Analyzer<\/code>&#8216;\u0131 kulland\u0131k, \u00e7\u00fcnk\u00fc bu bize AST \u00fczerinde kolayca gezinmemizi sa\u011flayan bir <code>ast.Inspector<\/code> nesnesi sunar. <code>run<\/code> fonksiyonu i\u00e7inde, <code>ast.Inspector<\/code>&#8216;\u0131 kullanarak AST&#8217;yi dola\u015f\u0131yor ve her <code>ast.ImportSpec<\/code> (import bildirimi) d\u00fc\u011f\u00fcm\u00fcn\u00fc kontrol ediyoruz. E\u011fer import yolu <code>&quot;fmt&quot;<\/code> ise, <code>pass.Reportf<\/code> ile bir hata mesaj\u0131 olu\u015fturuyoruz. Bu, Go&#8217;da bir linter&#8217;\u0131n temel \u00e7al\u0131\u015fma prensibidir.<\/p>\n<h2>Go Analyzer Framework&#8217;\u00fc ile Tan\u0131\u015fma: Detayl\u0131 Bir Bak\u0131\u015f<\/h2>\n<p>Go&#8217;nun linter ekosisteminin temelini olu\u015fturan <code>golang.org\/x\/tools\/go\/analysis<\/code> framework&#8217;\u00fc, statik analiz ara\u00e7lar\u0131 geli\u015ftirmek i\u00e7in standart ve g\u00fc\u00e7l\u00fc bir yol sunar. Bu framework, farkl\u0131 analiz\u00f6rlerin bir araya getirilerek karma\u015f\u0131k kontrollerin yap\u0131lmas\u0131n\u0131 kolayla\u015ft\u0131r\u0131r ve linter&#8217;lar\u0131n test edilebilirli\u011fini art\u0131r\u0131r. Bir <code>analysis.Analyzer<\/code> yap\u0131s\u0131, bir linter&#8217;\u0131n t\u00fcm kimli\u011fini ve davran\u0131\u015f\u0131n\u0131 tan\u0131mlayan merkezi bir bile\u015fendir. Hadi bu yap\u0131n\u0131n temel alanlar\u0131na daha yak\u0131ndan bakal\u0131m:<\/p>\n<ul>\n<li>\n<p><code>Name string<\/code>: Analiz\u00f6r\u00fcn benzersiz ad\u0131d\u0131r. Genellikle k\u00fc\u00e7\u00fck harfle ba\u015flar ve k\u0131sa, a\u00e7\u0131klay\u0131c\u0131 bir isimdir (\u00f6rne\u011fin, &#8220;nolint&#8221;, &#8220;unusedparams&#8221;).<\/p>\n<\/li>\n<li>\n<p><code>Doc string<\/code>: Analiz\u00f6r\u00fcn ne i\u015f yapt\u0131\u011f\u0131n\u0131 a\u00e7\u0131klayan k\u0131sa bir belgedir. Bu a\u00e7\u0131klama, kullan\u0131c\u0131lar\u0131n linter&#8217;\u0131n amac\u0131n\u0131 anlamalar\u0131na yard\u0131mc\u0131 olur.<\/p>\n<\/li>\n<li>\n<p><code>Run func(*analysis.Pass) (interface{}, error)<\/code>: Analiz\u00f6r\u00fcn ana mant\u0131\u011f\u0131n\u0131 i\u00e7eren fonksiyondur. Bu fonksiyon, bir <code>analysis.Pass<\/code> nesnesi al\u0131r. <code>Pass<\/code> nesnesi, analiz edilen paketin AST&#8217;si, tip bilgileri, dosya sistemindeki konumu ve di\u011fer ba\u011flam bilgilerini i\u00e7erir. <code>Run<\/code> fonksiyonu, buldu\u011fu sorunlar\u0131 <code>pass.Reportf<\/code> veya <code>pass.Report<\/code> metotlar\u0131 arac\u0131l\u0131\u011f\u0131yla raporlar. D\u00f6n\u00fc\u015f de\u011feri olarak <code>nil, nil<\/code> yayg\u0131n bir kullan\u0131md\u0131r, ancak baz\u0131 analiz\u00f6rler ileri analizler i\u00e7in sonu\u00e7 d\u00f6nd\u00fcrebilir.<\/p>\n<\/li>\n<li>\n<p><code>Requires []*analysis.Analyzer<\/code>: Bu analiz\u00f6r\u00fcn \u00e7al\u0131\u015fabilmesi i\u00e7in \u00f6nceden \u00e7al\u0131\u015ft\u0131r\u0131lmas\u0131 gereken di\u011fer analiz\u00f6rlerin listesidir. \u00d6rne\u011fin, AST \u00fczerinde gezmek i\u00e7in <code>inspect.Analyzer<\/code>&#8216;a, tip bilgileri i\u00e7in <code>types.Analyzer<\/code>&#8216;a ihtiya\u00e7 duyabilirsiniz. Bu, analiz\u00f6rlerin mod\u00fcler bir \u015fekilde birbirine ba\u011f\u0131ml\u0131 olmas\u0131n\u0131 sa\u011flar.<\/p>\n<\/li>\n<li>\n<p><code>FactTypes []analysis.Fact<\/code>: Analiz\u00f6r\u00fcn \u00fcretti\u011fi veya t\u00fcketti\u011fi &#8220;fact&#8221; (ger\u00e7ek) t\u00fcrlerini tan\u0131mlar. Fact&#8217;ler, analiz\u00f6rler aras\u0131nda bilgi payla\u015f\u0131m\u0131n\u0131 sa\u011flayan mekanizmalard\u0131r. \u00d6rne\u011fin, bir analiz\u00f6r bir fonksiyonun yan etkileri hakk\u0131nda bir fact \u00fcretebilir ve ba\u015fka bir analiz\u00f6r bu fact&#8217;i kullanarak farkl\u0131 bir kontrol yapabilir.<\/p>\n<\/li>\n<li>\n<p><code>ResultType reflect.Type<\/code>: <code>Run<\/code> metodunun d\u00f6nd\u00fcrd\u00fc\u011f\u00fc sonucun tipini belirtir. E\u011fer <code>Run<\/code> metodu bir de\u011fer d\u00f6nd\u00fcr\u00fcyorsa, bu alan o de\u011ferin tipini yans\u0131tmal\u0131d\u0131r.<\/p>\n<\/li>\n<\/ul>\n<p><code>analysis.Pass<\/code> yap\u0131s\u0131, bir analiz\u00f6r\u00fcn <code>Run<\/code> fonksiyonuna sa\u011flanan ana ba\u011flam nesnesidir. Bu nesne, bir analiz\u00f6r\u00fcn ihtiya\u00e7 duydu\u011fu t\u00fcm bilgilere eri\u015fim sa\u011flar:<\/p>\n<ul>\n<li>\n<p><code>Fset *token.FileSet<\/code>: Kaynak dosyalardaki konumlar\u0131 (sat\u0131r, s\u00fctun) izlemek i\u00e7in kullan\u0131lan dosya k\u00fcmesi.<\/p>\n<\/li>\n<li>\n<p><code>Files []*ast.File<\/code>: Analiz edilen paketteki her bir Go kaynak dosyas\u0131n\u0131n AST&#8217;si.<\/p>\n<\/li>\n<li>\n<p><code>Pkg *types.Package<\/code>: Analiz edilen paketin tip bilgileri.<\/p>\n<\/li>\n<li>\n<p><code>TypesInfo *types.Info<\/code>: AST d\u00fc\u011f\u00fcmleri ve bunlar\u0131n tipleri, tan\u0131mlar\u0131, kullan\u0131mlar\u0131 aras\u0131ndaki e\u015fle\u015fmeleri i\u00e7eren detayl\u0131 tip bilgileri.<\/p>\n<\/li>\n<li>\n<p><code>Reportf func(pos token.Pos, format string, args ...interface{})<\/code>: Bir hata veya uyar\u0131 raporlamak i\u00e7in kullan\u0131lan fonksiyondur. <code>pos<\/code> parametresi, hatan\u0131n kaynak kodundaki konumunu belirtir.<\/p>\n<\/li>\n<li>\n<p><code>ResultOf map[*analysis.Analyzer]interface{}<\/code>: <code>Requires<\/code> alan\u0131nda belirtilen di\u011fer analiz\u00f6rlerin d\u00f6nd\u00fcrd\u00fc\u011f\u00fc sonu\u00e7lara eri\u015fim sa\u011flar. \u00d6rne\u011fin, <code>inspect.Analyzer<\/code>&#8216;\u0131n sonucuna buradan eri\u015ferek bir <code>ast.Inspector<\/code> nesnesi elde ederiz.<\/p>\n<\/li>\n<\/ul>\n<p>AST \u00fczerinde gezinmek i\u00e7in en yayg\u0131n y\u00f6ntemlerden biri <code>ast.Inspect<\/code> fonksiyonudur. Bu fonksiyon, bir AST d\u00fc\u011f\u00fcm\u00fcn\u00fc ve bir gezgin (visitor) fonksiyonu al\u0131r. Gezgin fonksiyonu, a\u011fa\u00e7taki her d\u00fc\u011f\u00fcm i\u00e7in \u00e7a\u011fr\u0131l\u0131r. Bu sayede, a\u011fac\u0131n tamam\u0131n\u0131 veya belirli d\u00fc\u011f\u00fcm t\u00fcrlerini kolayca kontrol edebiliriz. \u00d6rne\u011fin, bir fonksiyon bildirimini (<code>ast.FuncDecl<\/code>), bir if ifadesini (<code>ast.IfStmt<\/code>) veya bir literal de\u011feri (<code>ast.BasicLit<\/code>) arayabiliriz. Bu framework&#8217;\u00fcn sa\u011flad\u0131\u011f\u0131 mod\u00fcler yap\u0131 ve kapsaml\u0131 bilgiler sayesinde, Go kod taban\u0131n\u0131z i\u00e7in \u00e7ok spesifik ve g\u00fc\u00e7l\u00fc statik analiz ara\u00e7lar\u0131 geli\u015ftirebilirsiniz.<\/p>\n<h2>Pratik Bir Linter Kural\u0131 Geli\u015ftirme: &#8220;Magic Number&#8221; Kontrol\u00fc<\/h2>\n<p>\u015eimdiye kadar temel linter yap\u0131s\u0131n\u0131 ve Go Analyzer framework&#8217;\u00fcn\u00fc \u00f6\u011frendik. Art\u0131k daha pratik ve yayg\u0131n bir kodlama sorununu ele alan bir linter kural\u0131 geli\u015ftirelim: &#8220;Magic Number&#8221; (sihirli say\u0131) kontrol\u00fc. &#8220;Magic number&#8221; terimi, kod i\u00e7inde do\u011frudan kullan\u0131lan, ancak anlam\u0131 belirsiz olan say\u0131sal sabitleri ifade eder. \u00d6rne\u011fin, bir dosya boyutunu kontrol etmek i\u00e7in <code>if size &gt; 1024 * 1024<\/code> yazmak yerine, <code>const MB = 1024 * 1024<\/code> tan\u0131mlay\u0131p <code>if size &gt; MB<\/code> yazmak \u00e7ok daha okunabilir ve s\u00fcrd\u00fcr\u00fclebilirdir. Magic number&#8217;lar, kodun anla\u015f\u0131l\u0131rl\u0131\u011f\u0131n\u0131 azalt\u0131r, hata yapma olas\u0131l\u0131\u011f\u0131n\u0131 art\u0131r\u0131r ve bak\u0131m\u0131n\u0131 zorla\u015ft\u0131r\u0131r. Linter&#8217;\u0131m\u0131z, do\u011frudan kullan\u0131lan say\u0131sal sabitleri tespit ederek geli\u015ftiricileri bu say\u0131lar\u0131 adland\u0131r\u0131lm\u0131\u015f sabitlere d\u00f6n\u00fc\u015ft\u00fcrmeye te\u015fvik edecek.<\/p>\n<p>Bu linter kural\u0131n\u0131 <code>internal\/mylinter\/mylinter.go<\/code> dosyam\u0131za ekleyelim veya mevcut <code>Analyzer<\/code> yap\u0131m\u0131z\u0131 g\u00fcncelleyelim. Amac\u0131m\u0131z, AST&#8217;yi gezerken <code>ast.BasicLit<\/code> (temel de\u011fi\u015fmez) d\u00fc\u011f\u00fcmlerini bulmak ve bunlar\u0131n bir say\u0131sal literal olup olmad\u0131\u011f\u0131n\u0131 kontrol etmektir. E\u011fer bir say\u0131sal literal ise ve bir <code>const<\/code> bildiriminin par\u00e7as\u0131 de\u011filse, bunu bir magic number olarak raporlayabiliriz. Ancak, daha basit bir ba\u015flang\u0131\u00e7 i\u00e7in, \u015fimdilik sadece do\u011frudan kullan\u0131lan say\u0131sal literal&#8217;lar\u0131 hedef alal\u0131m ve belirli istisnalar (\u00f6rne\u011fin 0, 1 gibi \u00e7ok yayg\u0131n say\u0131lar) d\u0131\u015f\u0131nda hepsini raporlayal\u0131m.<\/p>\n<div class=\"code-container\">\n<pre><code>\n\/\/ internal\/mylinter\/mylinter.go (G\u00fcncellenmi\u015f veya yeni Analyzer)\npackage mylinter\n\nimport (\n\t\"go\/ast\"\n\t\"go\/token\"\n\t\"golang.org\/x\/tools\/go\/analysis\"\n\t\"golang.org\/x\/tools\/go\/analysis\/passes\/inspect\"\n\t\"strconv\"\n)\n\n\/\/ Analyzer, linter'\u0131m\u0131z\u0131n ana tan\u0131m\u0131d\u0131r.\nvar Analyzer = &analysis.Analyzer{\n\tName: \"noMagicNumber\",\n\tDoc:  \"Do\u011frudan kullan\u0131lan 'magic number'lar\u0131 tespit eder ve sabit kullan\u0131m\u0131n\u0131 te\u015fvik eder.\",\n\tRun:  run,\n\tRequires: []*analysis.Analyzer{\n\t\tinspect.Analyzer,\n\t},\n}\n\nfunc run(pass *analysis.Pass) (interface{}, error) {\n\tinspector := pass.ResultOf[inspect.Analyzer].(*ast.Inspector)\n\n\t\/\/ Sadece say\u0131sal literal'lar\u0131 (\u00f6rne\u011fin 10, 3.14) kontrol etmek i\u00e7in filtre uygulayal\u0131m.\n\tnodeFilter := []ast.Node{\n\t\t(*ast.BasicLit)(nil),\n\t}\n\n\tinspector.Preorder(nodeFilter, func(n ast.Node) {\n\t\tlit := n.(*ast.BasicLit)\n\n\t\t\/\/ Sadece say\u0131sal literal'lar\u0131 (INT, FLOAT) kontrol edelim.\n\t\tif lit.Kind != token.INT && lit.Kind != token.FLOAT {\n\t\t\treturn\n\t\t}\n\n\t\t\/\/ Baz\u0131 yayg\u0131n ve genellikle kabul edilebilir say\u0131lar\u0131 (0, 1, -1) g\u00f6rmezden gelelim.\n\t\t\/\/ Bu listeyi projenizin ihtiya\u00e7lar\u0131na g\u00f6re geni\u015fletebilirsiniz.\n\t\tif lit.Value == \"0\" || lit.Value == \"1\" || lit.Value == \"-1\" {\n\t\t\treturn\n\t\t}\n\n\t\t\/\/ Say\u0131n\u0131n bir 'const' bildiriminin par\u00e7as\u0131 olup olmad\u0131\u011f\u0131n\u0131 kontrol edelim.\n\t\t\/\/ Bu, biraz daha karma\u015f\u0131k bir kontrol gerektirir.\n\t\t\/\/ \u015eimdilik, sadece literal'\u0131n bir 'const' ifadesi i\u00e7inde olup olmad\u0131\u011f\u0131n\u0131 kontrol etmek i\u00e7in\n\t\t\/\/ parent d\u00fc\u011f\u00fcmlerine bakabiliriz. Daha do\u011fru bir kontrol i\u00e7in 'types.Info' gerekebilir.\n\t\t\/\/ Basit bir yakla\u015f\u0131mla: E\u011fer literal bir 'const' bildirimi i\u00e7inde de\u011filse, raporla.\n\t\t\/\/ Bu kontrol tam do\u011fru olmayabilir, \u00e7\u00fcnk\u00fc bir ifadenin par\u00e7as\u0131 olan const'lar da olabilir.\n\t\t\/\/ Daha sa\u011flam bir kontrol i\u00e7in AST ba\u011flam\u0131n\u0131 daha derinlemesine incelemek gerekir.\n\t\t\/\/ \u015eimdilik, bu basit kontrol\u00fc kullanarak ilerleyelim.\n\n\t\t\/\/ Bir say\u0131sal literal'\u0131 int veya float olarak ayr\u0131\u015ft\u0131rmaya \u00e7al\u0131\u015fal\u0131m.\n\t\t\/\/ Ge\u00e7erli bir say\u0131sal de\u011fer oldu\u011fundan emin olal\u0131m.\n\t\t_, errInt := strconv.ParseInt(lit.Value, 0, 64)\n\t\t_, errFloat := strconv.ParseFloat(lit.Value, 64)\n\n\t\tif errInt == nil || errFloat == nil { \/\/ Ge\u00e7erli bir say\u0131sal de\u011ferse\n\t\t\t\/\/ E\u011fer literal bir 'const' bildirimi i\u00e7inde de\u011filse raporlayal\u0131m.\n\t\t\t\/\/ Bu kontrol\u00fc basitle\u015ftirmek ad\u0131na, \u015fimdilik her say\u0131sal literal'\u0131 magic number olarak kabul edelim\n\t\t\t\/\/ ve sadece \"0\", \"1\", \"-1\" gibi istisnalar\u0131 hari\u00e7 tutal\u0131m.\n\t\t\t\/\/ Ger\u00e7ek bir linter'da, bu kontrol\u00fcn daha sofistike olmas\u0131 gerekir (\u00f6rne\u011fin, bir atama ifadesinin sa\u011f taraf\u0131nda m\u0131, bir const bildirimi i\u00e7inde mi vb.).\n\n\t\t\tpass.Reportf(lit.Pos(), \"magic number '%s' kullan\u0131l\u0131yor; l\u00fctfen adland\u0131r\u0131lm\u0131\u015f bir sabit kullan\u0131n\", lit.Value)\n\t\t}\n\t})\n\n\treturn nil, nil\n}\n  <\/code><\/pre>\n<\/div>\n<p>Yukar\u0131daki kodda, <code>ast.BasicLit<\/code> t\u00fcr\u00fcndeki d\u00fc\u011f\u00fcmleri hedef al\u0131yoruz. <code>lit.Kind<\/code> ile literal&#8217;\u0131n t\u00fcr\u00fcn\u00fc kontrol ediyoruz (<code>token.INT<\/code> veya <code>token.FLOAT<\/code>). Ard\u0131ndan, &#8220;0&#8221;, &#8220;1&#8221;, &#8220;-1&#8221; gibi yayg\u0131n ve genellikle kabul edilebilir say\u0131lar\u0131 atl\u0131yoruz. E\u011fer bu ko\u015fullar sa\u011flan\u0131rsa, <code>pass.Reportf<\/code> ile bir hata raporluyoruz. Bu, linter&#8217;\u0131m\u0131z\u0131n magic number&#8217;lar\u0131 tespit etmesini sa\u011flar. Daha geli\u015fmi\u015f bir linter&#8217;da, bir literal&#8217;\u0131n bir <code>const<\/code> bildiriminin par\u00e7as\u0131 olup olmad\u0131\u011f\u0131n\u0131 veya bir <code>iota<\/code> ifadesi i\u00e7inde kullan\u0131l\u0131p kullan\u0131lmad\u0131\u011f\u0131n\u0131 kontrol etmek i\u00e7in AST ba\u011flam\u0131n\u0131 daha derinlemesine incelemeniz gerekebilir. Ancak bu \u00f6rnek, temel bir kural\u0131 nas\u0131l uygulayaca\u011f\u0131n\u0131z\u0131 g\u00f6stermek i\u00e7in yeterlidir.<\/p>\n<h2>Linter&#8217;\u0131n\u0131z\u0131 Test Etme ve Entegre Etme<\/h2>\n<p>Linter&#8217;\u0131m\u0131z\u0131 geli\u015ftirdikten sonra, do\u011fru \u00e7al\u0131\u015ft\u0131\u011f\u0131ndan emin olmak i\u00e7in test etmemiz ve geli\u015ftirme i\u015f ak\u0131\u015f\u0131m\u0131za entegre etmemiz gerekir. Go&#8217;nun <code>go\/analysis\/analysistest<\/code> paketi, analiz\u00f6rleri test etmek i\u00e7in \u00f6zel olarak tasarlanm\u0131\u015f g\u00fc\u00e7l\u00fc bir ara\u00e7t\u0131r. Bu paket, test senaryolar\u0131n\u0131z\u0131 kolayca tan\u0131mlaman\u0131za ve analiz\u00f6r\u00fcn\u00fcz\u00fcn beklenen hatalar\u0131 do\u011fru bir \u015fekilde raporlay\u0131p raporlamad\u0131\u011f\u0131n\u0131 do\u011frulaman\u0131za olanak tan\u0131r.<\/p>\n<h3>Linter&#8217;\u0131 Yerel Olarak \u00c7al\u0131\u015ft\u0131rma<\/h3>\n<p>Linter&#8217;\u0131m\u0131z\u0131 yerel olarak \u00e7al\u0131\u015ft\u0131rmak i\u00e7in, <code>cmd\/mylinter\/main.go<\/code> dosyam\u0131z\u0131 a\u015fa\u011f\u0131daki gibi d\u00fczenlememiz gerekiyor. Bu dosya, <code>singlechecker<\/code> paketini kullanarak bizim <code>Analyzer<\/code>&#8216;\u0131m\u0131z\u0131 \u00e7al\u0131\u015ft\u0131r\u0131r.<\/p>\n<div class=\"code-container\">\n<pre><code>\n\/\/ cmd\/mylinter\/main.go\npackage main\n\nimport (\n\t\"github.com\/kullaniciadi\/mylinter\/internal\/mylinter\"\n\t\"golang.org\/x\/tools\/go\/analysis\/singlechecker\"\n)\n\nfunc main() {\n\tsinglechecker.Main(mylinter.Analyzer)\n}\n  <\/code><\/pre>\n<\/div>\n<p>\u015eimdi, linter&#8217;\u0131m\u0131z\u0131 test etmek i\u00e7in \u00f6rnek bir Go dosyas\u0131 olu\u015ftural\u0131m: <code>testdata\/test.go<\/code>.<\/p>\n<div class=\"code-container\">\n<pre><code>\n\/\/ testdata\/test.go\npackage testdata\n\nimport \"fmt\" \/\/ Bu sat\u0131r fmt paketi kullan\u0131m\u0131n\u0131 raporlamal\u0131\n\nconst (\n\tMyConst = 100 \/\/ Bu bir magic number de\u011fil\n\tAnotherConst = 2\n)\n\nfunc DoSomething(value int) int {\n\tresult := value * 5 \/\/ 5 bir magic number, raporlanmal\u0131\n\tif result > 10 { \/\/ 10 bir magic number, raporlanmal\u0131\n\t\tfmt.Println(\"Result is greater than\", 10) \/\/ Hem fmt hem de 10 raporlanmal\u0131\n\t\treturn result + 3 \/\/ 3 bir magic number, raporlanmal\u0131\n\t}\n\treturn result\n}\n\nfunc IgnoreZeroOne() {\n\t_ = 0 \/\/ Raporlanmamal\u0131\n\t_ = 1 \/\/ Raporlanmamal\u0131\n\t_ = -1 \/\/ Raporlanmamal\u0131\n}\n  <\/code><\/pre>\n<\/div>\n<p>Linter&#8217;\u0131m\u0131z\u0131 \u00e7al\u0131\u015ft\u0131rmak i\u00e7in: (E\u011fer <code>noFmtImport<\/code> linter&#8217;\u0131n\u0131 kullan\u0131yorsan\u0131z, <code>internal\/mylinter\/mylinter.go<\/code> dosyas\u0131ndaki <code>Analyzer<\/code> de\u011fi\u015fkenini <code>noFmtImportAnalyzer<\/code> veya benzeri bir isimle de\u011fi\u015ftirmeniz ve <code>singlechecker.Main<\/code> i\u00e7inde do\u011fru <code>Analyzer<\/code>&#8216;\u0131 \u00e7a\u011f\u0131rman\u0131z gerekebilir. Bu \u00f6rnekte <code>noMagicNumber<\/code> analiz\u00f6r\u00fcn\u00fc varsay\u0131yoruz.)<\/p>\n<div class=\"code-container\">\n<pre><code>\ngo run .\/cmd\/mylinter .\/testdata\/...\n  <\/code><\/pre>\n<\/div>\n<p>Bu komut, linter&#8217;\u0131n\u0131z\u0131 \u00e7al\u0131\u015ft\u0131racak ve <code>testdata<\/code> dizinindeki Go dosyalar\u0131n\u0131 analiz edecektir. Beklentimiz, <code>fmt<\/code> paketi import edildi\u011finde ve magic number&#8217;lar kullan\u0131ld\u0131\u011f\u0131nda hata mesajlar\u0131 g\u00f6rmektir.<\/p>\n<h3>Test Yazma (<code>analysistest<\/code> ile)<\/h3>\n<p>Daha sa\u011flam bir test yakla\u015f\u0131m\u0131 i\u00e7in <code>analysistest<\/code> paketini kullanal\u0131m. <code>internal\/mylinter\/mylinter_test.go<\/code> dosyas\u0131n\u0131 olu\u015ftural\u0131m:<\/p>\n<div class=\"code-container\">\n<pre><code>\n\/\/ internal\/mylinter\/mylinter_test.go\npackage mylinter_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com\/kullaniciadi\/mylinter\/internal\/mylinter\"\n\t\"golang.org\/x\/tools\/go\/analysis\/analysistest\"\n)\n\nfunc TestNoMagicNumber(t *testing.T) {\n\t\/\/ Test verilerinin bulundu\u011fu dizin.\n\t\/\/ Bu dizin, test i\u00e7in Go kaynak dosyalar\u0131n\u0131 i\u00e7erecektir.\n\ttestdata := analysistest.TestData()\n\n\t\/\/ Analiz\u00f6r\u00fcm\u00fcz\u00fc ve test veri k\u00fcmemizi \u00e7al\u0131\u015ft\u0131ral\u0131m.\n\t\/\/ <code>analysistest.Run<\/code> fonksiyonu, analiz\u00f6r\u00fcn belirli test senaryolar\u0131 \u00fczerinde\n\t\/\/ nas\u0131l davrand\u0131\u011f\u0131n\u0131 kontrol etmemizi sa\u011flar.\n\t\/\/ <code>analysistest.Run(t, testdata, mylinter.Analyzer, &quot;a&quot;)<\/code>\n\t\/\/ \"a\" paketi, testdata dizinindeki 'a' adl\u0131 paketi analiz etmesini s\u00f6yler.\n\t\/\/ Bu durumda, testdata dizininde 'a' adl\u0131 bir paket olu\u015fturmam\u0131z gerekecek.\n\tanalysistest.Run(t, testdata, mylinter.Analyzer, \"a\")\n}\n  <\/code><\/pre>\n<\/div>\n<p>\u015eimdi, test verilerimizi <code>testdata\/src\/a<\/code> dizini alt\u0131na yerle\u015ftirelim. <code>analysistest<\/code> paketi, <code>\/\/ want &quot;hata mesaj\u0131&quot;<\/code> yorumlar\u0131n\u0131 kullanarak beklenen hatalar\u0131 otomatik olarak kontrol eder.<\/p>\n<div class=\"code-container\">\n<pre><code>\n\/\/ testdata\/src\/a\/a.go\npackage a\n\nimport \"fmt\" \/\/ want \"fmt paketi kullan\u0131lamaz, l\u00fctfen \u00f6zel loglama paketinizi kullan\u0131n.\"\n\nconst (\n\tMyConst = 100\n\tAnotherConst = 2\n)\n\nfunc DoSomething(value int) int {\n\tresult := value * 5 \/\/ want \"magic number '5' kullan\u0131l\u0131yor; l\u00fctfen adland\u0131r\u0131lm\u0131\u015f bir sabit kullan\u0131n\"\n\tif result > 10 { \/\/ want \"magic number '10' kullan\u0131l\u0131yor; l\u00fctfen adland\u0131r\u0131lm\u0131\u015f bir sabit kullan\u0131n\"\n\t\tfmt.Println(\"Result is greater than\", 10) \/\/ want \"fmt paketi kullan\u0131lamaz, l\u00fctfen \u00f6zel loglama paketinizi kullan\u0131n.\" \/\/ want \"magic number '10' kullan\u0131l\u0131yor; l\u00fctfen adland\u0131r\u0131lm\u0131\u015f bir sabit kullan\u0131n\"\n\t\treturn result + 3 \/\/ want \"magic number '3' kullan\u0131l\u0131yor; l\u00fctfen adland\u0131r\u0131lm\u0131\u015f bir sabit kullan\u0131n\"\n\t}\n\treturn result\n}\n\nfunc IgnoreZeroOne() {\n\t_ = 0\n\t_ = 1\n\t_ = -1\n}\n  <\/code><\/pre>\n<\/div>\n<p>\u015eimdi testleri \u00e7al\u0131\u015ft\u0131r\u0131n:<\/p>\n<div class=\"code-container\">\n<pre><code>\ngo test .\/internal\/mylinter\n  <\/code><\/pre>\n<\/div>\n<p>Bu, linter&#8217;\u0131n\u0131z\u0131n beklenen hatalar\u0131 do\u011fru bir \u015fekilde yakalay\u0131p yakalamad\u0131\u011f\u0131n\u0131 do\u011frulayacakt\u0131r. <code>analysistest<\/code> paketi, <code>\/\/ want<\/code> yorumlar\u0131n\u0131 tarayarak, linter&#8217;\u0131n bu konumlarda belirtilen mesajlarla hata raporlamas\u0131n\u0131 bekler.<\/p>\n<h3>CI\/CD S\u00fcre\u00e7lerine Entegrasyon<\/h3>\n<p>Linter&#8217;\u0131n\u0131z\u0131 geli\u015ftirme i\u015f ak\u0131\u015f\u0131n\u0131za entegre etmek, kod kalitesini s\u00fcrekli olarak y\u00fcksek tutman\u0131n anahtar\u0131d\u0131r. Bunu genellikle CI\/CD (S\u00fcrekli Entegrasyon\/S\u00fcrekli Teslimat) boru hatlar\u0131nda yapars\u0131n\u0131z. \u00d6rne\u011fin, GitHub Actions, GitLab CI\/CD veya Jenkins gibi ara\u00e7larda, her kod g\u00f6nderimi (push) veya \u00e7ekme iste\u011fi (pull request) \u00fczerinde linter&#8217;\u0131n\u0131z\u0131 otomatik olarak \u00e7al\u0131\u015ft\u0131rabilirsiniz.<\/p>\n<p>\u00d6rnek bir GitHub Actions yap\u0131land\u0131rmas\u0131 (<code>.github\/workflows\/lint.yml<\/code>):<\/p>\n<div class=\"code-container\">\n<pre><code>\nname: Lint\n\non: [push, pull_request]\n\njobs:\n  lint:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions\/checkout@v3\n    - uses: actions\/setup-go@v4\n      with:\n        go-version: '1.21'\n    - name: Run my custom linter\n      run: |\n        go run .\/cmd\/mylinter .\/...\n  <\/code><\/pre>\n<\/div>\n<p>Bu yap\u0131land\u0131rma, her push ve pull request&#8217;te Go projenizi kontrol edecek ve \u00f6zel linter&#8217;\u0131n\u0131z\u0131 t\u00fcm kod taban\u0131 \u00fczerinde \u00e7al\u0131\u015ft\u0131racakt\u0131r. E\u011fer linter herhangi bir hata raporlarsa, CI\/CD ad\u0131m\u0131 ba\u015far\u0131s\u0131z olacak ve bu da geli\u015ftiricilerin sorunlar\u0131 birle\u015ftirmeden \u00f6nce d\u00fczeltmelerini sa\u011flayacakt\u0131r. Bu sayede, kod taban\u0131n\u0131z\u0131n s\u00fcrekli olarak y\u00fcksek kalitede kalmas\u0131n\u0131 garantilemi\u015f olursunuz.<\/p>\n<h2>\u0130leri D\u00fczey Linter Geli\u015ftirme \u0130pu\u00e7lar\u0131<\/h2>\n<p>Temel bir linter olu\u015fturmay\u0131 ve test etmeyi \u00f6\u011frendik. \u015eimdi, linter&#8217;\u0131n\u0131z\u0131 daha g\u00fc\u00e7l\u00fc ve esnek hale getirecek baz\u0131 ileri d\u00fczey ipu\u00e7lar\u0131na g\u00f6z atal\u0131m. Bu ipu\u00e7lar\u0131, daha karma\u015f\u0131k senaryolar\u0131 ele alman\u0131za ve linter&#8217;\u0131n\u0131z\u0131 projenizin \u00f6zel ihtiya\u00e7lar\u0131na g\u00f6re daha iyi uyarlaman\u0131za yard\u0131mc\u0131 olacakt\u0131r.<\/p>\n<h3>1. Konfig\u00fcrasyon Se\u00e7enekleri Ekleme<\/h3>\n<p>Bir linter&#8217;\u0131n her zaman ayn\u0131 kurallar\u0131 uygulamas\u0131 yerine, kullan\u0131c\u0131lar\u0131n belirli parametreleri yap\u0131land\u0131rmas\u0131na izin vermek \u00e7ok daha kullan\u0131\u015fl\u0131d\u0131r. \u00d6rne\u011fin, &#8220;magic number&#8221; linter&#8217;\u0131m\u0131zda, hangi say\u0131lar\u0131n g\u00f6z ard\u0131 edilece\u011fini veya hangi e\u015fik de\u011ferlerinin kullan\u0131laca\u011f\u0131n\u0131 yap\u0131land\u0131r\u0131labilir hale getirebiliriz. <code>analysis.Analyzer<\/code> yap\u0131s\u0131, <code>Flags<\/code> ad\u0131nda bir alan i\u00e7erir. Bu alan, standart Go <code>flag<\/code> paketiyle uyumlu \u00e7al\u0131\u015f\u0131r ve linter&#8217;\u0131n\u0131za komut sat\u0131r\u0131 arg\u00fcmanlar\u0131 arac\u0131l\u0131\u011f\u0131yla konfig\u00fcrasyon eklemenizi sa\u011flar.<\/p>\n<div class=\"code-container\">\n<pre><code>\n\/\/ internal\/mylinter\/mylinter.go (\u00d6rnek konfig\u00fcrasyon ekleme)\n\/\/ ...\nvar (\n\tignoreZeros bool\n\tminMagicNumber int\n)\n\nvar Analyzer = &analysis.Analyzer{\n\tName: \"noMagicNumber\",\n\tDoc:  \"Do\u011frudan kullan\u0131lan 'magic number'lar\u0131 tespit eder ve sabit kullan\u0131m\u0131n\u0131 te\u015fvik eder.\",\n\tRun:  run,\n\tRequires: []*analysis.Analyzer{\n\t\tinspect.Analyzer,\n\t},\n\t\/\/ Flags alan\u0131n\u0131 kullanarak komut sat\u0131r\u0131 arg\u00fcmanlar\u0131 ekleyelim.\n\tFlags: func() flag.FlagSet {\n\t\tfs := flag.NewFlagSet(\"noMagicNumber\", flag.ExitOnError)\n\t\tfs.BoolVar(&ignoreZeros, \"ignore-zeros\", true, \"0 ve 1 say\u0131lar\u0131n\u0131 magic number olarak g\u00f6rmezden gel.\")\n\t\tfs.IntVar(&minMagicNumber, \"min-magic-number\", 2, \"Bu de\u011ferin alt\u0131ndaki say\u0131lar\u0131 magic number olarak g\u00f6rmezden gel.\")\n\t\treturn *fs\n\t}(),\n}\n\nfunc run(pass *analysis.Pass) (interface{}, error) {\n\t\/\/ ...\n\tif ignoreZeros && (lit.Value == \"0\" || lit.Value == \"1\" || lit.Value == \"-1\") {\n\t\treturn\n\t}\n\t\/\/ minMagicNumber kontrol\u00fcn\u00fc de ekleyebilirsiniz.\n\t\/\/ ...\n}\n  <\/code><\/pre>\n<\/div>\n<p>Bu sayede, linter&#8217;\u0131n\u0131z\u0131 <code>go run .\/cmd\/mylinter -ignore-zeros=false -min-magic-number=5 .\/...<\/code> gibi komutlarla \u00e7al\u0131\u015ft\u0131rarak davran\u0131\u015f\u0131n\u0131 de\u011fi\u015ftirebilirsiniz.<\/p>\n<h3>2. Birden Fazla Kural Y\u00f6netimi ve Kural Gruplar\u0131<\/h3>\n<p>Ger\u00e7ek d\u00fcnya linter&#8217;lar\u0131 genellikle birden fazla kural i\u00e7erir. Her kural\u0131 ayr\u0131 bir <code>analysis.Analyzer<\/code> olarak tan\u0131mlamak ve sonra bunlar\u0131 tek bir ana linter arac\u0131nda birle\u015ftirmek iyi bir uygulamad\u0131r. <code>singlechecker.Main<\/code> yerine, birden fazla analiz\u00f6r\u00fc \u00e7al\u0131\u015ft\u0131rmak i\u00e7in <code>multichecker.Main<\/code> kullanabilirsiniz.<\/p>\n<div class=\"code-container\">\n<pre><code>\n\/\/ cmd\/mylinter\/main.go (Birden fazla analiz\u00f6r i\u00e7in)\npackage main\n\nimport (\n\t\"github.com\/kullaniciadi\/mylinter\/internal\/mylinter\"\n\t\"github.com\/kullaniciadi\/mylinter\/internal\/noFmtImport\" \/\/ Yeni bir analiz\u00f6r paketi varsayal\u0131m\n\t\"golang.org\/x\/tools\/go\/analysis\/multichecker\"\n)\n\nfunc main() {\n\tmultichecker.Main(\n\t\tmylinter.Analyzer,      \/\/ Magic number kontrol\u00fc\n\t\tnoFmtImport.Analyzer, \/\/ Fmt import kontrol\u00fc (yeni bir analiz\u00f6r)\n\t\t\/\/ Di\u011fer analiz\u00f6rlerinizi buraya ekleyin\n\t)\n}\n  <\/code><\/pre>\n<\/div>\n<p>Bu yakla\u015f\u0131m, kodunuzu mod\u00fcler tutar ve her kural\u0131n ba\u011f\u0131ms\u0131z olarak geli\u015ftirilmesini ve test edilmesini sa\u011flar.<\/p>\n<h3>3. Tip Bilgilerini Kullanma (<code>types.Info<\/code>)<\/h3>\n<p>Bazen sadece AST yap\u0131s\u0131n\u0131 incelemek yeterli olmayabilir; bir de\u011fi\u015fkenin veya ifadenin ger\u00e7ek tipini bilmek isteyebilirsiniz. <code>analysis.Pass<\/code> nesnesi i\u00e7indeki <code>TypesInfo *types.Info<\/code> alan\u0131, derleyici taraf\u0131ndan toplanan tip bilgilerine eri\u015fim sa\u011flar. Bu, daha karma\u015f\u0131k ve anlamsal analizler yapman\u0131z\u0131 sa\u011flar. \u00d6rne\u011fin, bir fonksiyonun belirli bir aray\u00fcz\u00fc uygulay\u0131p uygulamad\u0131\u011f\u0131n\u0131 veya bir de\u011fi\u015fkenin belirli bir t\u00fcre sahip olup olmad\u0131\u011f\u0131n\u0131 kontrol edebilirsiniz.<\/p>\n<div class=\"code-container\">\n<pre><code>\n\/\/ \u00d6rnek: Bir fonksiyonun d\u00f6n\u00fc\u015f tipini kontrol etme\nfunc runWithTypes(pass *analysis.Pass) (interface{}, error) {\n\tinspector := pass.ResultOf[inspect.Analyzer].(*ast.Inspector)\n\tnodeFilter := []ast.Node{(*ast.FuncDecl)(nil)}\n\n\tinspector.Preorder(nodeFilter, func(n ast.Node) {\n\t\tfuncDecl := n.(*ast.FuncDecl)\n\t\tif funcDecl.Type.Results != nil && len(funcDecl.Type.Results.List) > 0 {\n\t\t\t\/\/ \u0130lk d\u00f6n\u00fc\u015f de\u011ferinin tipini alal\u0131m\n\t\t\tfirstResultField := funcDecl.Type.Results.List[0]\n\t\t\ttv := pass.TypesInfo.TypeOf(firstResultField.Type)\n\t\t\tif tv != nil && tv.String() == \"error\" {\n\t\t\t\t\/\/ E\u011fer ilk d\u00f6n\u00fc\u015f tipi error ise, bir kontrol yapabiliriz.\n\t\t\t\t\/\/ \u00d6rne\u011fin, fonksiyonun ad\u0131n\u0131n \"handle\" ile ba\u015flay\u0131p ba\u015flamad\u0131\u011f\u0131n\u0131 kontrol edebiliriz.\n\t\t\t\tif !strings.HasPrefix(funcDecl.Name.Name, \"handle\") {\n\t\t\t\t\tpass.Reportf(funcDecl.Pos(), \"error d\u00f6nd\u00fcren fonksiyonlar\u0131n 'handle' ile ba\u015flamas\u0131 \u00f6nerilir\")\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t})\n\treturn nil, nil\n}\n  <\/code><\/pre>\n<\/div>\n<p>Tip bilgileri, Go&#8217;nun g\u00fc\u00e7l\u00fc tip sisteminden tam olarak yararlanarak \u00e7ok daha anlaml\u0131 linter kurallar\u0131 yazman\u0131za olanak tan\u0131r.<\/p>\n<h3>4. Performans Optimizasyonu<\/h3>\n<p>B\u00fcy\u00fck kod tabanlar\u0131nda linter&#8217;lar yava\u015f \u00e7al\u0131\u015fabilir. Performans\u0131 art\u0131rmak i\u00e7in \u015funlar\u0131 g\u00f6z \u00f6n\u00fcnde bulundurun:<\/p>\n<ul>\n<li><strong>Gereksiz AST gezintilerinden ka\u00e7\u0131n\u0131n:<\/strong> Sadece ihtiyac\u0131n\u0131z olan d\u00fc\u011f\u00fcm t\u00fcrlerini filtreleyin (<code>nodeFilter<\/code>).<\/li>\n<li><strong>Erken \u00e7\u0131k\u0131\u015f yap\u0131n:<\/strong> Bir kural ihlali buldu\u011funuzda veya bir ko\u015ful sa\u011flanmad\u0131\u011f\u0131nda fonksiyondan erken d\u00f6n\u00fcn.<\/li>\n<li><strong>\u00d6nbellekleme:<\/strong> E\u011fer ayn\u0131 bilgiyi tekrar tekrar hesaplaman\u0131z gerekiyorsa, bunu \u00f6nbelle\u011fe al\u0131n.<\/li>\n<\/ul>\n<p>Bu ileri d\u00fczey teknikler, linter&#8217;\u0131n\u0131z\u0131 sadece bir hata yakalama arac\u0131 olmaktan \u00e7\u0131kar\u0131p, projenizin \u00f6zel ihtiya\u00e7lar\u0131na g\u00f6re \u015fekillendirilmi\u015f, ak\u0131ll\u0131 bir kod asistan\u0131na d\u00f6n\u00fc\u015ft\u00fcrmenize yard\u0131mc\u0131 olacakt\u0131r.<\/p>\n<h2>Sonu\u00e7 ve S\u0131k\u00e7a Sorulan Sorular<\/h2>\n<p>Bu makalede, Go dilinde kendi linter&#8217;\u0131n\u0131z\u0131 olu\u015fturman\u0131n temellerini ad\u0131m ad\u0131m inceledik. Neden linter&#8217;lara ihtiya\u00e7 duydu\u011fumuzdan, Go&#8217;nun Soyut S\u00f6zdizimi A\u011fac\u0131 (AST) yap\u0131s\u0131na ve <code>golang.org\/x\/tools\/go\/analysis<\/code> framework&#8217;\u00fcn\u00fcn g\u00fcc\u00fcne kadar bir\u00e7ok konuyu ele ald\u0131k. &#8220;Magic Number&#8221; kontrol\u00fc gibi pratik bir kural geli\u015ftirerek \u00f6\u011frendiklerimizi peki\u015ftirdik ve linter&#8217;\u0131m\u0131z\u0131 nas\u0131l test edip CI\/CD s\u00fcre\u00e7lerine entegre edece\u011fimizi g\u00f6rd\u00fck. Son olarak, konfig\u00fcrasyon, \u00e7oklu kural y\u00f6netimi ve tip bilgisi kullan\u0131m\u0131 gibi ileri d\u00fczey ipu\u00e7lar\u0131yla linter geli\u015ftirme becerilerimizi bir ad\u0131m \u00f6teye ta\u015f\u0131d\u0131k. Kendi linter&#8217;\u0131n\u0131z\u0131 geli\u015ftirmek, sadece kod kalitenizi art\u0131rmakla kalmaz, ayn\u0131 zamanda Go&#8217;nun i\u00e7 i\u015fleyi\u015fi hakk\u0131nda derinlemesine bilgi edinmenizi de sa\u011flar. Bu yolculuk, daha temiz, daha tutarl\u0131 ve daha g\u00fcvenilir Go kodlar\u0131 yazman\u0131z i\u00e7in size g\u00fc\u00e7l\u00fc bir ara\u00e7 seti sunacakt\u0131r. Unutmay\u0131n, iyi kod sadece \u00e7al\u0131\u015fan kod de\u011fil, ayn\u0131 zamanda okunabilir, s\u00fcrd\u00fcr\u00fclebilir ve hatas\u0131z olan koddur.<\/p>\n<h3>S\u0131k\u00e7a Sorulan Sorular (SSS)<\/h3>\n<p><strong>1. Neden kendi linter&#8217;\u0131m\u0131 yazmal\u0131y\u0131m, zaten bir\u00e7ok Go linter&#8217;\u0131 yok mu?<\/strong><br \/>\nEvet, Go ekosisteminde bir\u00e7ok harika linter (\u00f6rne\u011fin <code>golangci-lint<\/code>) bulunmaktad\u0131r. Ancak, bazen projenize veya ekibinize \u00f6zel, \u00e7ok ni\u015f kodlama standartlar\u0131 veya k\u0131s\u0131tlamalar\u0131n\u0131z olabilir. Mevcut linter&#8217;lar\u0131n kapsamad\u0131\u011f\u0131 bu \u00f6zel durumlar i\u00e7in kendi linter&#8217;\u0131n\u0131z\u0131 yazmak, tam kontrol ve esneklik sa\u011flar. Ayr\u0131ca, bu s\u00fcre\u00e7 Go&#8217;nun statik analiz yetenekleri hakk\u0131nda derinlemesine bilgi edinmenize de yard\u0131mc\u0131 olur.<\/p>\n<p><strong>2. <code>go\/ast<\/code> ve <code>go\/analysis<\/code> aras\u0131ndaki fark nedir?<\/strong><br \/>\n<code>go\/ast<\/code> paketi, Go kaynak kodunun Soyut S\u00f6zdizimi A\u011fac\u0131 (AST) temsilini sa\u011flar ve bu a\u011fa\u00e7 \u00fczerinde gezinmek i\u00e7in temel ara\u00e7lar\u0131 i\u00e7erir. <code>go\/analysis<\/code> ise, bu AST \u00fczerinde statik analizler yapmak i\u00e7in daha y\u00fcksek seviyeli bir framework (yaz\u0131l\u0131m \u00e7er\u00e7evesi) sunar. <code>go\/analysis<\/code>, analiz\u00f6rlerinizi yap\u0131land\u0131rman\u0131za, di\u011fer analiz\u00f6rlerle etkile\u015fim kurman\u0131za ve standart bir \u015fekilde raporlama yapman\u0131za olanak tan\u0131r. K\u0131sacas\u0131, <code>go\/ast<\/code> ham veriyi sa\u011flarken, <code>go\/analysis<\/code> bu veriyi i\u015flemek i\u00e7in bir yap\u0131 ve ara\u00e7 seti sunar.<\/p>\n<p><strong>3. Linter&#8217;\u0131m\u0131n performans\u0131n\u0131 nas\u0131l art\u0131rabilirim?<\/strong><br \/>\nPerformans optimizasyonu i\u00e7in birka\u00e7 strateji vard\u0131r: Gereksiz AST d\u00fc\u011f\u00fcmlerini gezmekten ka\u00e7\u0131nmak i\u00e7in <code>nodeFilter<\/code> kullan\u0131n. Kural ihlali tespit edildi\u011finde veya bir ko\u015ful sa\u011flanmad\u0131\u011f\u0131nda <code>run<\/code> fonksiyonundan erken d\u00f6n\u00fcn. E\u011fer ayn\u0131 hesaplamalar\u0131 tekrar tekrar yap\u0131yorsan\u0131z, sonu\u00e7lar\u0131 \u00f6nbelle\u011fe al\u0131n. B\u00fcy\u00fck kod tabanlar\u0131nda, sadece de\u011fi\u015fen dosyalar\u0131 analiz etmek i\u00e7in ak\u0131ll\u0131 \u00f6nbellekleme mekanizmalar\u0131 d\u00fc\u015f\u00fcnebilirsiniz.<\/p>\n<p><strong>4. Linter&#8217;\u0131m\u0131 di\u011fer Go ara\u00e7lar\u0131yla nas\u0131l entegre edebilirim?<\/strong><br \/>\nLinter&#8217;\u0131n\u0131z\u0131 <code>multichecker.Main<\/code> kullanarak di\u011fer \u00f6zel analiz\u00f6rlerinizle birle\u015ftirebilirsiniz. Ayr\u0131ca, <code>golangci-lint<\/code> gibi pop\u00fcler linter ara\u00e7lar\u0131, \u00f6zel <code>analysis.Analyzer<\/code>&#8216;lar\u0131n\u0131z\u0131 bir eklenti olarak \u00e7al\u0131\u015ft\u0131rma yetene\u011fi sunar. Bu, linter&#8217;\u0131n\u0131z\u0131n daha geni\u015f bir Go geli\u015ftirme ekosistemi i\u00e7inde kullan\u0131lmas\u0131n\u0131 sa\u011flar. CI\/CD sistemlerine entegrasyon i\u00e7in ise, makalede g\u00f6sterildi\u011fi gibi basit bir <code>go run .\/cmd\/mylinter .\/...<\/code> komutu yeterlidir.<\/p>\n<p><strong>5. Linter&#8217;\u0131mda karma\u015f\u0131k tip kontrolleri yapmak m\u00fcmk\u00fcn m\u00fc?<\/strong><br \/>\nKesinlikle. <code>analysis.Pass<\/code> nesnesi i\u00e7indeki <code>TypesInfo *types.Info<\/code> alan\u0131, derleyici taraf\u0131ndan toplanan t\u00fcm tip bilgilerine eri\u015fmenizi sa\u011flar. Bu sayede, de\u011fi\u015fkenlerin, fonksiyonlar\u0131n ve ifadelerin ger\u00e7ek tiplerini, aray\u00fcz uygulamalar\u0131n\u0131 ve di\u011fer anlamsal bilgileri kontrol edebilirsiniz. Bu, sadece s\u00f6zdizimsel de\u011fil, ayn\u0131 zamanda anlamsal olarak do\u011fru kod yaz\u0131lmas\u0131n\u0131 sa\u011flayan \u00e7ok daha g\u00fc\u00e7l\u00fc kurallar olu\u015fturman\u0131za olanak tan\u0131r.<\/p>\n<p>#GoProgramlama #Linter #StatikAnaliz #KodKalitesi #Yaz\u0131l\u0131mGeli\u015ftirme #GoLang<\/p>\n<div class=\"github-example-link\"><strong>\u00d6rnek kod:<\/strong> <a href=\"https:\/\/github.com\/fatihsoysalcom\/go-custom-linter-max-parameters\" target=\"_blank\" rel=\"noopener noreferrer\">github.com\/fatihsoysalcom\/go-custom-linter-max-parameters<\/a><\/div>\n","protected":false},"excerpt":{"rendered":"Yaz\u0131l\u0131m geli\u015ftirme s\u00fcrecinde kod kalitesi, tutarl\u0131l\u0131k ve hata tespiti her zaman \u00f6ncelikli konular olmu\u015ftur.","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"csco_page_header_type":"","csco_page_load_nextpost":"","csco_page_subscribe_form":"","csco_page_contact_form":"","footnotes":""},"categories":[1],"tags":[],"class_list":{"0":"post-42123","1":"post","2":"type-post","3":"status-publish","4":"format-standard","6":"category-genel","7":"cs-entry","8":"cs-video-wrap"},"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v20.5 (Yoast SEO v25.3.1) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Go Dilinde \u0130lk Linter&#039;\u0131n\u0131z\u0131 Nas\u0131l Olu\u015fturursunuz? - Kodlar\u0131n Gizemli D\u00fcnyas\u0131<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/fatihsoysal.com\/blog\/go-dilinde-ilk-linterinizi-nasil-olusturursunuz\/\" \/>\n<meta property=\"og:locale\" content=\"tr_TR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Go Dilinde \u0130lk Linter&#039;\u0131n\u0131z\u0131 Nas\u0131l Olu\u015fturursunuz?\" \/>\n<meta property=\"og:description\" content=\"Yaz\u0131l\u0131m geli\u015ftirme s\u00fcrecinde kod kalitesi, tutarl\u0131l\u0131k ve hata tespiti her zaman \u00f6ncelikli konular olmu\u015ftur.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/fatihsoysal.com\/blog\/go-dilinde-ilk-linterinizi-nasil-olusturursunuz\/\" \/>\n<meta property=\"og:site_name\" content=\"Kodlar\u0131n Gizemli D\u00fcnyas\u0131\" \/>\n<meta property=\"article:published_time\" content=\"2026-05-27T18:07:16+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-05-27T18:07:48+00:00\" \/>\n<meta name=\"author\" content=\"Fatih Soysal\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Yazan:\" \/>\n\t<meta name=\"twitter:data1\" content=\"Fatih Soysal\" \/>\n\t<meta name=\"twitter:label2\" content=\"Tahmini okuma s\u00fcresi\" \/>\n\t<meta name=\"twitter:data2\" content=\"27 dakika\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/go-dilinde-ilk-linterinizi-nasil-olusturursunuz\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/go-dilinde-ilk-linterinizi-nasil-olusturursunuz\/\"},\"author\":{\"name\":\"Fatih Soysal\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\"},\"headline\":\"Go Dilinde \u0130lk Linter&#8217;\u0131n\u0131z\u0131 Nas\u0131l Olu\u015fturursunuz?\",\"datePublished\":\"2026-05-27T18:07:16+00:00\",\"dateModified\":\"2026-05-27T18:07:48+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/go-dilinde-ilk-linterinizi-nasil-olusturursunuz\/\"},\"wordCount\":3886,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\"},\"inLanguage\":\"tr\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/fatihsoysal.com\/blog\/go-dilinde-ilk-linterinizi-nasil-olusturursunuz\/#respond\"]}],\"copyrightYear\":\"2026\",\"copyrightHolder\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/go-dilinde-ilk-linterinizi-nasil-olusturursunuz\/\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/go-dilinde-ilk-linterinizi-nasil-olusturursunuz\/\",\"name\":\"Go Dilinde \u0130lk Linter'\u0131n\u0131z\u0131 Nas\u0131l Olu\u015fturursunuz? - Kodlar\u0131n Gizemli D\u00fcnyas\u0131\",\"isPartOf\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#website\"},\"datePublished\":\"2026-05-27T18:07:16+00:00\",\"dateModified\":\"2026-05-27T18:07:48+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/go-dilinde-ilk-linterinizi-nasil-olusturursunuz\/#breadcrumb\"},\"inLanguage\":\"tr\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/fatihsoysal.com\/blog\/go-dilinde-ilk-linterinizi-nasil-olusturursunuz\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/go-dilinde-ilk-linterinizi-nasil-olusturursunuz\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Anasayfa\",\"item\":\"https:\/\/fatihsoysal.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Go Dilinde \u0130lk Linter&#8217;\u0131n\u0131z\u0131 Nas\u0131l Olu\u015fturursunuz?\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#website\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/\",\"name\":\"Fatihsoysal.com\",\"description\":\"Blog - Yaz\u0131l\u0131m D\u00fcnyas\u0131 Tecr\u00fcbelerim\",\"publisher\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/fatihsoysal.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"tr\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\",\"name\":\"Fatih Soysal\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"tr\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png\",\"contentUrl\":\"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png\",\"width\":512,\"height\":512,\"caption\":\"Fatih Soysal\"},\"logo\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/\"},\"description\":\"Kullan\u0131m ve kodlama m\u00fckemmeliyetini odak alan uygulamalar olu\u015fturma deneyimine sahip, profesyonel olarak 15+ y\u0131l \u00fczeri deneyime sahip bir yaz\u0131l\u0131m m\u00fchendisi.\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/author\/fatihsoysal\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Go Dilinde \u0130lk Linter'\u0131n\u0131z\u0131 Nas\u0131l Olu\u015fturursunuz? - Kodlar\u0131n Gizemli D\u00fcnyas\u0131","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/fatihsoysal.com\/blog\/go-dilinde-ilk-linterinizi-nasil-olusturursunuz\/","og_locale":"tr_TR","og_type":"article","og_title":"Go Dilinde \u0130lk Linter'\u0131n\u0131z\u0131 Nas\u0131l Olu\u015fturursunuz?","og_description":"Yaz\u0131l\u0131m geli\u015ftirme s\u00fcrecinde kod kalitesi, tutarl\u0131l\u0131k ve hata tespiti her zaman \u00f6ncelikli konular olmu\u015ftur.","og_url":"https:\/\/fatihsoysal.com\/blog\/go-dilinde-ilk-linterinizi-nasil-olusturursunuz\/","og_site_name":"Kodlar\u0131n Gizemli D\u00fcnyas\u0131","article_published_time":"2026-05-27T18:07:16+00:00","article_modified_time":"2026-05-27T18:07:48+00:00","author":"Fatih Soysal","twitter_card":"summary_large_image","twitter_misc":{"Yazan:":"Fatih Soysal","Tahmini okuma s\u00fcresi":"27 dakika"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/fatihsoysal.com\/blog\/go-dilinde-ilk-linterinizi-nasil-olusturursunuz\/#article","isPartOf":{"@id":"https:\/\/fatihsoysal.com\/blog\/go-dilinde-ilk-linterinizi-nasil-olusturursunuz\/"},"author":{"name":"Fatih Soysal","@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1"},"headline":"Go Dilinde \u0130lk Linter&#8217;\u0131n\u0131z\u0131 Nas\u0131l Olu\u015fturursunuz?","datePublished":"2026-05-27T18:07:16+00:00","dateModified":"2026-05-27T18:07:48+00:00","mainEntityOfPage":{"@id":"https:\/\/fatihsoysal.com\/blog\/go-dilinde-ilk-linterinizi-nasil-olusturursunuz\/"},"wordCount":3886,"commentCount":0,"publisher":{"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1"},"inLanguage":"tr","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/fatihsoysal.com\/blog\/go-dilinde-ilk-linterinizi-nasil-olusturursunuz\/#respond"]}],"copyrightYear":"2026","copyrightHolder":{"@id":"https:\/\/fatihsoysal.com\/blog\/#organization"}},{"@type":"WebPage","@id":"https:\/\/fatihsoysal.com\/blog\/go-dilinde-ilk-linterinizi-nasil-olusturursunuz\/","url":"https:\/\/fatihsoysal.com\/blog\/go-dilinde-ilk-linterinizi-nasil-olusturursunuz\/","name":"Go Dilinde \u0130lk Linter'\u0131n\u0131z\u0131 Nas\u0131l Olu\u015fturursunuz? - Kodlar\u0131n Gizemli D\u00fcnyas\u0131","isPartOf":{"@id":"https:\/\/fatihsoysal.com\/blog\/#website"},"datePublished":"2026-05-27T18:07:16+00:00","dateModified":"2026-05-27T18:07:48+00:00","breadcrumb":{"@id":"https:\/\/fatihsoysal.com\/blog\/go-dilinde-ilk-linterinizi-nasil-olusturursunuz\/#breadcrumb"},"inLanguage":"tr","potentialAction":[{"@type":"ReadAction","target":["https:\/\/fatihsoysal.com\/blog\/go-dilinde-ilk-linterinizi-nasil-olusturursunuz\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/fatihsoysal.com\/blog\/go-dilinde-ilk-linterinizi-nasil-olusturursunuz\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Anasayfa","item":"https:\/\/fatihsoysal.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Go Dilinde \u0130lk Linter&#8217;\u0131n\u0131z\u0131 Nas\u0131l Olu\u015fturursunuz?"}]},{"@type":"WebSite","@id":"https:\/\/fatihsoysal.com\/blog\/#website","url":"https:\/\/fatihsoysal.com\/blog\/","name":"Fatihsoysal.com","description":"Blog - Yaz\u0131l\u0131m D\u00fcnyas\u0131 Tecr\u00fcbelerim","publisher":{"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/fatihsoysal.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"tr"},{"@type":["Person","Organization"],"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1","name":"Fatih Soysal","image":{"@type":"ImageObject","inLanguage":"tr","@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/","url":"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png","contentUrl":"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png","width":512,"height":512,"caption":"Fatih Soysal"},"logo":{"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/"},"description":"Kullan\u0131m ve kodlama m\u00fckemmeliyetini odak alan uygulamalar olu\u015fturma deneyimine sahip, profesyonel olarak 15+ y\u0131l \u00fczeri deneyime sahip bir yaz\u0131l\u0131m m\u00fchendisi.","url":"https:\/\/fatihsoysal.com\/blog\/author\/fatihsoysal\/"}]}},"yoast_meta":{"yoast_wpseo_title":"","yoast_wpseo_metadesc":"","yoast_wpseo_canonical":""},"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts\/42123","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/comments?post=42123"}],"version-history":[{"count":1,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts\/42123\/revisions"}],"predecessor-version":[{"id":42124,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts\/42123\/revisions\/42124"}],"wp:attachment":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/media?parent=42123"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/categories?post=42123"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/tags?post=42123"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}