362 American Academic Scientific Research Journal for Engineering, Technology, and Sciences ISSN (Print) 2313-4410, ISSN (Online) 2313-4402 https://asrjetsjournal.org/index.php/American_Scientific_Journal/index Complex Methods of Static Code Analysis in Go: Combination of Classical Approaches and Modern Tools Denis Isaev* Engineering Director at Yandex Cloud,Moscow, Russia Email: solovyeva.vasilisa13@gmail.com Abstract The paper explores comprehensive approaches to static code analysis for Go, highlighting both foundational theory and advanced practical applications. After examining theoretical constructs—such as abstract syntax trees and rule-based detection—this work presents an overview of current trends, including aggregators like GolangCI-Lint. Attention is given to integrating specialized linters (e.g., misspell, unparam, prealloc, bearer) to bolster detection accuracy and address security vulnerabilities. Through detailed practical examples, the article illustrates how automated reports in pull requests facilitate early bug identification and remediation. Configuration strategies for continuous integration and delivery (CI/CD) pipelines are also outlined, focusing on harnessing multi-layered analysis for improved coverage. Concluding remarks emphasize the importance of combined static analysis tools, domain-specific checkers, and regular inspections to achieve high levels of reliability, readability, and security in Go codebases. Keywords: Go language; static analysis; linters; aggregators; code quality; CI/CD; security; performance optimization. 1.Introduction With the rising popularity of the Go programming language [1, 2] and its extensive adoption in building high- performance, scalable systems, the need for reliable methods to ensure code quality and security becomes increasingly urgent. Among the tools currently available for such control, static code analysis stands out for its ability to detect potential defects, vulnerabilities, and style violations in the early stages of software development [3, 4]. Identifying problems at an early phase not only reduces the effort required for subsequent fixes but also contributes to the overall robustness of the final product [5].Go has gained its popularity thanks to features such as simple syntax, built-in concurrency mechanisms, and a rich ecosystem of libraries [1]. ------------------------------------------------------------------------ Received: 7/9/2025 Accepted: 9/9/2025 Published: 11/19/2025 ------------------------------------------------------------------------ * Corresponding author. https://asrjetsjournal.org/index.php/American_Scientific_Journal/index American Academic Scientific Research Journal for Engineering, Technology, and Sciences (ASRJETS) - Volume 103, No 1, pp 362-372 363 Nonetheless, even a user-friendly language demands rigorous code review to prevent regressions and bugs. Manual checks of large codebases can be both labor-intensive and prone to oversight. Consequently, the automation offered by static analysis tools has become a cornerstone for modern software development processes. A variety of foundational works discuss both the theoretical underpinnings and practical techniques of static analysis. Early research on lexical and syntactic parsing, abstract syntax trees, and rule-based checks is provided by Hopkroft and his colleagues [3], establishing the formal language models upon which most static analysis frameworks are built. Subsequent studies have focused on overcoming the challenges of false positives and false negatives and on developing specialized analyzers capable of handling complex language features [4, 5, 6]. Empirical observations on the use of static analysis in Go-based projects indicate that combining multiple linters can be particularly beneficial. Examples include GolangCI-lint, which aggregates several checkers, and additional specialized tools like misspell and prealloc, which address specific categories of issues. Moreover, some development teams employ automated static checks directly in pull requests, thus integrating continuous feedback and promoting timely code improvements. Several structured reviews of Go-specific analyzers [7,9] have categorized available solutions into standalone analyzers and aggregators, elucidating their design principles and strengths. The specialized focus on data-flow vulnerabilities [9] underscores that many classical analyzers do not cover certain complex scenarios, such as unsafe pointer operations. Against this backdrop, the present study aims not only to characterize existing solutions but also to demonstrate a broader practical approach for their combined application in real-world development pipelines. A closer examination of the cited structured reviews reveals a common focus on categorization and feature comparison. Although invaluable for understanding the landscape of available tools, these studies often stop short of demonstrating the practical synergies and integration complexities involved in a real-world CI/CD pipeline. For instance, while they might describe both an aggregator like GolangCI-Lint and a security scanner like bearer, the necessity of their combined application to cover security gaps left by general-purpose checks is not always the central focus. This study seeks to bridge that specific gap by focusing on the how—the practical implementation and configuration of a multi-layered strategy. The aim of this research is to enhance and expand the practical techniques for static code analysis of Go projects by drawing upon a wide range of contemporary studies and established best practices [1,9]. 2. Theoretical foundations and modern trends in Go static analysis Static analysis of Go code involves interpreting program structure without executing it, relying on abstract syntax trees (ASTs) and predefined rules to identify potential defects or deviations from best practices [3, 5, 6]. Recent works emphasize that despite improvements in tool accuracy, certain limitations persist due to the inherent complexity of algorithmic verification [4, 9].A key theoretical challenge is the absence of a universally accepted mathematical model that precisely captures all possible algorithmic behaviors [3, 5]. As a result, many American Academic Scientific Research Journal for Engineering, Technology, and Sciences (ASRJETS) - Volume 103, No 1, pp 362-372 364 analyzers rely on approximations, which can produce both false positives (where a correct segment of code is flagged as erroneous) and false negatives (where an actual defect goes undetected). This limitation underscores the need for ongoing refinement of static analysis tools and the importance of complementary testing methodologies, such as runtime checks or dynamic analysis [4]. Static analysis in Go typically proceeds by parsing source files into an AST, then traversing the AST to apply pattern-matching rules or more advanced data-flow heuristics [1, 2]. Certain analyzers also integrate type inference or symbolic execution for deeper inspection of possible program states [9]. Nevertheless, the complexity of concurrency in Go—especially channels and goroutines—can further complicate a purely static approach, sometimes requiring partial instrumentation or specialized concurrency-focused checkers [4, 7]. In an effort to categorize the wide array of available tools, researchers have constructed solution maps showing how different analyzers intersect or are fully subsumed by comprehensive aggregators [2]. Among the available solutions, GolangCI-Lint stands out as one of the most prominent aggregators. It combines multiple built-in linters, including staticcheck, misspell, and prealloc, thus covering a broad set of checks ranging from stylistic issues to potential performance optimizations [7, 8]. Its main strengths include the ease of configuration through a single .golangci.yml file and the ability to disable or enable specific linters. However, GolangCI-Lint may produce a high volume of alerts, some of which are false positives; fine-tuning of rules is therefore vital to minimize noise [5, 6]. Certain standalone analyzers like unparam (for detecting unused function parameters) and misspell (for identifying common typos) integrate seamlessly into aggregator workflows [7, 9]. These tools excel in their targeted domains but may offer limited utility for broader or more nuanced checks, such as data-flow or concurrency issues. Additionally, prealloc focuses on slice optimizations, highlighting places in code where preallocated slices could reduce memory overhead. While beneficial for performance-sensitive projects, prealloc warnings are not always universally applicable; developers must confirm whether such optimizations align with the overall design [4]. Beyond these widely known options, other aggregators, such as goreporter or gometalinter, often rely on the same underlying analyzers present in GolangCI-Lint. Consequently, their outputs can be largely redundant, although some provide distinct reporting interfaces [2]. Tools like bearer aim to identify security-sensitive patterns related to file permissions, external commands, and potential data leaks [9]. These specialized analyzers complement broader aggregators by focusing on intricate vulnerabilities often overlooked by generic checks. However, their coverage may be narrower, demanding additional tools for a more comprehensive audit. The table below (Table 1) summarizes key features, advantages, and drawbacks of major static analysis solutions for Go, reflecting both aggregators and standalone linters referenced in the literature and open-source documentation. American Academic Scientific Research Journal for Engineering, Technology, and Sciences (ASRJETS) - Volume 103, No 1, pp 362-372 365 Table 1: Key features, advantages, and drawbacks of major static analysis solutions for Go [2, 7-9] Tool / aggregator Key features Advantages Limitations GolangCI-Lint Aggregates multiple linters (e.g., staticcheck, misspell, etc.) Centralized configuration; broad coverage of styling, correctness, and performance checks Possible over-reporting; demands rule fine-tuning to reduce noise unparam Detects unused parameters Pinpoints potential code smells and simplifications Limited to one specific check; no concurrency or data-flow analysis misspell Identifies common typos Fast, simple detection of spelling mistakes, improving readability Does not address deeper semantic errors prealloc Suggests slice preallocation Helps optimize memory usage in performance-critical segments May be excessive for smaller-scale or non–performance-critical projects; can produce low-impact warnings bearer Scans for security patterns (e.g., file permissions, leaks) Detects specific vulnerabilities (command injection, insecure file handling) Coverage limited to certain classes of security flaws; may require additional tools for concurrency or cryptography goreporter Aggregator calling many of the same linters as GolangCI- Lint Combined output for multiple checks, potential for a single integrated report Often duplicates results from GolangCI-Lint; minor differences in reporting style gometalinter Another aggregator relying on existing standalone linters Historical aggregator used before GolangCI-Lint; can run multiple checks in one pass Less actively maintained; overlaps heavily with GolangCI-Lint In conclusion, the modern trend in Go static analysis leans toward aggregator solutions that consolidate multiple linters, thus reducing integration complexity and providing a single interface for configuring and reviewing results Reference [4, 9]. At the same time, specialized tools remain essential for targeting specific types of errors, such as security vulnerabilities or unused parameters. Striking a balance between a broad-scope aggregator and carefully selected supplemental analyzers can yield a comprehensive and efficient static analysis pipeline. 3. Expanded practical approach based on prior work In many real-world Go projects, static analysis is implemented as an automated process integrated into development workflows, including continuous integration (CI) pipelines and pull request reviews [7, 9]. Several practical examples illustrate the added value of static analysis in maintaining code quality and security. Below are snippets and explanations adapted from a documented workflow involving the GolangCI-Lint aggregator, along with additional specialized linters. The referenced code listings show how issues like unused parameters, typos, potential data leaks, and more were discovered and addressed. American Academic Scientific Research Journal for Engineering, Technology, and Sciences (ASRJETS) - Volume 103, No 1, pp 362-372 366 Example 1: Detecting Unused Parameters (unparam) $ golangci-lint run --no-config --disable-all -E unparam --print-linter-name=false syntax/printer.go:134:50: (*printer).addWhitespace - text is unused func (p *printer) addWhitespace(kind ctrlSymbol, text string) { ^ ssa/dom_test.go:165:40: benchmarkDominators - size always receives 10000 func benchmarkDominators(b *testing.B, size int, bg blockGen) { ^ Figure1 In these findings, the parameter text in the addWhitespace function is never used, and the parameter size in benchmarkDominators is statically set to 10000 across different test scenarios. Although such issues might not always break functionality, they contribute to code clutter and can obscure the intent of the software [5, 6]. Renaming variables with _ (blank identifier) or removing them altogether can improve clarity. Example 2: Identifying Typos (misspell) Another linter, misspell, quickly flags common spelling mistakes: $ time golangci-lint run --no-config --disable-all -E misspell --print-linter- name=false config/services/servicesConfig.go:60:20: compability is a misspelling of compatibility // Keep backwards compability. ^ helpers/language.go:49:24: referenece is a misspelling of reference // absolute directory referenece. It is what we get. ^ Figure2 Despite their seeming triviality, such errors can degrade the readability of code and documentation, potentially hindering collaboration [1, 2]. Configuring the locale for misspell (e.g., US or UK) ensures consistent spelling throughout the project. Example 3: Encouraging Preallocation (prealloc) For certain performance-critical scenarios, prealloc suggests preallocating slices: American Academic Scientific Research Journal for Engineering, Technology, and Sciences (ASRJETS) - Volume 103, No 1, pp 362-372 367 func (gcToolchain) pack(b *Builder, a *Action, afile string, ofiles []string) error { var absOfiles []string for _, f := range ofiles { absOfiles = append(absOfiles, mkAbs(a.Objdir, f)) } // ... } Replacing the above with: absOfiles := make([]string, 0, len(ofiles)) Figure3 can, in theory, reduce allocations in memory-intensive loops. However, excessive micro-optimizations may not always justify added complexity [4]. Beyond these specific linters, the CI system generated comprehensive pull request reports, indicating newly introduced issues and referencing code lines requiring attention [8]. According to reported metrics, the frequency of unaddressed style warnings, typos, and minor performance concerns decreased significantly once developers began consistently reviewing these automated reports. A noteworthy observation is that certain problems—such as insecure file handling or potential command injection—were not covered by the default set of linters in GolangCI-Lint [9]. Consequently, additional security- focused analyzers (for instance, bearer) were introduced to flag vulnerabilities related to file permissions, unsanitized user input, or unsafe deserialization [2, 7]. In practice, a multilayered approach harnessing both comprehensive aggregators and specialized security linters has proven advantageous. For example, GolangCI-Lint performs broad checks across style, correctness, and minor performance issues, while a targeted linter like bearer inspects potential security hazards. This synergy reduces the likelihood of missing critical classes of bugs and yields more actionable reports [3, 9]. Moreover, concurrency-focused static analyzers—though fewer in number—complement these general tools by catching Goroutine mismanagement and channel misuse. Incorporating specialized concurrency checks can avert complex race conditions and deadlocks, issues often overlooked by purely syntactic or rule-based analyzers [4, 6]. Ultimately, a well-structured combination of general-purpose aggregators, domain-specific linters, and targeted security or concurrency checks broadens the coverage of static analysis. Such layering also helps mitigate the risk of false negatives that would otherwise slip through a single-tool system [5]. In summary, real-world experience with GolangCI-Lint, unparam, misspell, prealloc, and additional niche analyzers confirms the value of a multi-analyzer strategy. Pull request–based workflows, bolstered by aggregated reporting, have demonstrated a measurable improvement in code consistency, maintainability, and security American Academic Scientific Research Journal for Engineering, Technology, and Sciences (ASRJETS) - Volume 103, No 1, pp 362-372 368 posture [2, 7, 8]. As Go evolves and new static analysis techniques emerge, adopting a layered approach remains a robust method to ensure high-quality, secure software development. 4. Practical recommendations and integration examples Effective static analysis depends not only on the choice of analyzers but also on how these tools are integrated into development workflows [7, 9]. Achieving a seamless setup often requires deliberate configuration in continuous integration (CI) pipelines, as well as clear strategies for interpreting and acting on reported findings.In practice, developers commonly rely on aggregator platforms like GolangCI-Lint to orchestrate multiple linters and generate a unified report. Additional custom scripts or specialized analyzers (e.g., bearer, prealloc) can be invoked in parallel, ensuring comprehensive coverage. 4.1. Setup and automation in CI/CD A common pattern is to incorporate static analysis checks as separate steps in a CI pipeline (e.g., GitHub Actions, GitLab CI, Jenkins), thus preventing the merging of pull requests that introduce critical defects. Configuring .golangci.yml plays a crucial role in tailoring GolangCI-Lint to project-specific needs [7]. Below is a simplified snippet illustrating how to enable specific linters, skip certain directories, and refine concurrency settings: Figure 4 American Academic Scientific Research Journal for Engineering, Technology, and Sciences (ASRJETS) - Volume 103, No 1, pp 362-372 369 In this configuration, directories commonly containing dependencies or generated code are skipped, reducing noise from files typically outside manual control. Additionally, each linter’s parameters are fine-tuned to align with internal development guidelines [1, 2]. For instance, depguard is set up to forbid importing logrus in most parts of the code, ensuring a consistent logging standard across the project. Automation in CI/CD involves not only running the static analysis but also publishing the results. According to the “Report for a GitHub Pull Request” documentation, each integration adds a “Details” link next to the pull request status. Developers can then click through to view a consolidated report detailing any newly introduced errors. This workflow encourages early detection of style regressions, unused parameters, or security-related oversights, forcing teams to address them before code merges into the main branch [6]. 4.2. Typical usage scenarios and error analysis When properly configured, GolangCI-Lint and additional analyzers detect a broad range of issues. For instance, unparam identifies redundant function parameters, while misspell highlights typographical errors in comments and documentation. Below is an illustrative code sample—adapted from the prior material—showing how misconfigurations can manifest: Figure 5 American Academic Scientific Research Journal for Engineering, Technology, and Sciences (ASRJETS) - Volume 103, No 1, pp 362-372 370 Figure 6 1.Unused parameter warning (unparam): The unusedParam flag might never be utilized in the function body, a situation flagged by unparam. Repeated occurrences of such a pattern could indicate improper design or legacy code that needs refactoring [5]. 2.Spelling or textual issues (misspell): If a developer inadvertently writes “messgae” instead of “message” in the logs or comments, misspell catches it quickly [1, 2]. Besides these relatively straightforward checks, more complex scenarios involve data-flow analysis or concurrency patterns [9]. Certain analyzers examine how data travels through functions to uncover potential null-pointer dereferences, while concurrency-focused tools may detect Goroutines that never terminate or channels susceptible to deadlocks [4]. However, according to recent reviews [2], not all analyzers excel at deeper data-flow validation, and specialized solutions—sometimes proprietary—are needed for thorough concurrency checks. A classic example involves the risk of dereferencing a nil pointer if an upstream function returns nil under certain conditions. While plain AST-based linters might not catch this, a more advanced static analyzer or partial symbolic execution engine could raise an alert [9]. To handle advanced cases, one approach is to integrate a second or third specialized tool alongside GolangCI- Lint. For instance, a security-focused linter can complement typical checks by examining file I/O and input sanitization (bearer or other vulnerability detectors), while a concurrency checker addresses Goroutine usage and potential race conditions [6]. This multi-layer setup, already discussed in the context of expanded practicality, significantly lowers the risk of missing critical bugs. In summary, configuring GolangCI-Lint and companion linters in a CI/CD environment fosters continuous vigilance against both minor and serious coding flaws. By combining aggregator-based checks (unparam, misspell, prealloc) with specialized or security-focused analyses (bearer, concurrency tools), teams can adopt a comprehensive, proactive stance on code quality. The final integration step—actionable reports in pull requests—ensures that every contributor remains accountable for addressing flagged issues, maintaining elevated standards of clarity, safety, and performance across all code contributions. The practical examples presented in Sections 2 and 3 confirm the efficacy of this layered strategy. While the American Academic Scientific Research Journal for Engineering, Technology, and Sciences (ASRJETS) - Volume 103, No 1, pp 362-372 371 aggregator (GolangCI-Lint) effectively manages common code quality issues like unused parameters or typos , its true value is realized as an orchestrator. However, as noted, this broad coverage often fails to detect domain- specific vulnerabilities, such as insecure file handling or potential command injection. The integration of specialized analyzers like bearer is therefore not optional but essential for addressing these critical gaps. This synergistic approach—using an aggregator for breadth and specialized tools for depth—directly mitigates the risks of false negatives and provides a more robust defense than any single tool could offer, validating the practical recommendations outlined. It is important to acknowledge the constraints of this analysis. 1. First, the study focuses on illustrating a combined approach using a representative, popular set of open- source tools (e.g., GolangCI-Lint, bearer). It does not present an exhaustive benchmark or comparative review against all available proprietary or alternative static analysis solutions. 2. Second, the assessment of tool effectiveness is qualitative, based on practical integration examples and documented issue detection (as shown in Section 2) , rather than quantitative metrics such as false positive/negative rates or performance overhead. 3. Finally, the Go ecosystem and its analysis tools are rapidly evolving; the specific configurations and tools highlighted represent a robust approach at the time of writing but will require adaptation as new techniques emerge. 5.Conclusion In conclusion, this study underscores the crucial role of comprehensive static analysis in modern Go development. By combining foundational rule-based checking with specialized linters and security-focused tools, it is possible to detect a wide spectrum of issues—from trivial typographical errors to subtle concurrency pitfalls. Practical examples and configuration guidelines reveal that multi-layered strategies, integrated into CI/CD pipelines, can significantly enhance both reliability and maintainability. The evidence gathered confirms that addressing defects early in the development cycle not only reduces technical debt but also improves collaboration by delivering actionable insights directly in pull requests. As Go continues to evolve and face diverse use cases, ongoing refinement of static analysis frameworks remains imperative. Future work could include deeper data-flow analysis and a tighter coupling of static and dynamic checks, ensuring that emerging paradigms of concurrency, security, and performance are rigorously addressed. References [1]. Esilevsky S. Programming languages of the “new wave”. Go language // System Administrator. - 2021. - №. 7-8. - С. 65-73. [2]. Galiev R. M., Evdoshenko O. I. REVIEW OF EXISTING SOLUTIONS FOR STATIC ANALYSIS OF GOLANG CODE //Inzhenerno-stroitel'nyi vestnik Prikaspiya. - 2024. - №. 2 (48). - С. 73-76.[5] [3]. Hopcroft D. E., Motwani R., Ullman D. Introduction to the theory of automata, languages and computation. - 2008. American Academic Scientific Research Journal for Engineering, Technology, and Sciences (ASRJETS) - Volume 103, No 1, pp 362-372 372 [4]. Menshikov M. A. Review of static analyzer service models // Proceedings of the Institute of system programming of the Russian Academy of Sciences. - 2021. - Т. 33. - №. 3. - С. 27-40. [5]. Koshelev V. K. Formalization of error detection in static symbolic execution // Proceedings of the Institute of System Programming of the Russian Academy of Sciences. - 2016. - Т. 28. - №. 5. - С. 105-118. [6]. Afanasyev V. O., Dvortsova V. V., Borodin A.. Е. Static analyzer for languages with exception handling // Proceedings of the Institute of System Programming of RAS. - 2022. - Т. 34. - №. 6. - С. 7- 28. [7]. Register of static analyzers //analysis-tools.dev. - Access mode: https://analysis-tools.dev/ [8]. Documentation of the micro project // https://github.com. - Access mode: https://github.com/zyedidia/micro [9]. Borodin A. E. et al. Search for vulnerabilities of insecure use of labeled data in the Svace static analyzer // Proceedings of the Institute of System Programming of the Russian Academy of Sciences. - 2021. - Т. 33. - №. 1. - С. 7-32.