<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Nguyễn Phúc Vinh</title>
    <description>The latest articles on Forem by Nguyễn Phúc Vinh (@phucvinh57).</description>
    <link>https://forem.com/phucvinh57</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F651648%2F97f22274-2e58-4080-af0c-34245914bacf.jpeg</url>
      <title>Forem: Nguyễn Phúc Vinh</title>
      <link>https://forem.com/phucvinh57</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/phucvinh57"/>
    <language>en</language>
    <item>
      <title>Introducing Biopass: Modern Multi-Modal Biometric Login for Linux</title>
      <dc:creator>Nguyễn Phúc Vinh</dc:creator>
      <pubDate>Fri, 27 Feb 2026 09:32:30 +0000</pubDate>
      <link>https://forem.com/phucvinh57/introducing-biopass-modern-multi-modal-biometric-login-for-linux-44kp</link>
      <guid>https://forem.com/phucvinh57/introducing-biopass-modern-multi-modal-biometric-login-for-linux-44kp</guid>
      <description>&lt;p&gt;If you use Linux on a modern laptop, you've probably envied the seamless Windows Hello experience—combining face, fingerprint, and PIN into one cohesive authentication system.&lt;/p&gt;

&lt;p&gt;Historically, Linux has lacked a modern, unified equivalent. While the community has incredible tools like &lt;a href="https://github.com/boltgolt/howdy" rel="noopener noreferrer"&gt;Howdy&lt;/a&gt;, it focuses exclusively on facial recognition, relies on CLI for management, and hasn't seen significant updates recently.&lt;/p&gt;

&lt;p&gt;That's why &lt;a href="https://github.com/thaitran24" rel="noopener noreferrer"&gt;@thaitran24&lt;/a&gt; and I (&lt;a href="https://github.com/phucvinh57" rel="noopener noreferrer"&gt;@phucvinh57&lt;/a&gt;) decided to build &lt;a href="https://github.com/TickLabVN/biopass" rel="noopener noreferrer"&gt;&lt;strong&gt;Biopass&lt;/strong&gt;&lt;/a&gt;: A fast, secure, and privacy-focused biometric authentication suite for Linux desktops supporting face, fingerprint, and eventually voice.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Biopass?
&lt;/h2&gt;

&lt;p&gt;We wanted to build something that goes beyond simple facial recognition, providing a robust, multi-modal suite with a great user experience.&lt;/p&gt;

&lt;p&gt;Here is how Biopass compares to existing solutions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Multiple Modalities&lt;/strong&gt;: Supports both Face and Fingerprint natively (with Voice on the roadmap).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Face Anti-Spoofing&lt;/strong&gt;: Built-in liveness detection. You don't necessarily need an expensive IR camera for basic security against photo-spoofing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Modern Interface&lt;/strong&gt;: Say goodbye to terminal configurations. Biopass comes with a beautiful desktop GUI to manage your biometric settings.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Key Features
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Flexible Authentication Setup&lt;/strong&gt;: You can register multiple biometrics. Authentication can run in parallel (whichever recognizes you first wins) or sequentially.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Robust Face Auth&lt;/strong&gt;: Combines recognition with advanced anti-spoofing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fingerprint Support&lt;/strong&gt;: Seamless integration for quick OS-level unlocks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Privacy First&lt;/strong&gt;: Everything runs entirely locally on your machine.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwb43e95tryzz3uorbm9t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwb43e95tryzz3uorbm9t.png" alt=" " width="800" height="972"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftdoz58hk67g0a2fx1sdk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftdoz58hk67g0a2fx1sdk.png" alt=" " width="800" height="972"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Under the Hood: The Tech Stack
&lt;/h2&gt;

&lt;p&gt;We built Biopass with performance and security in mind, splitting it into two primary layers:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. The Core PAM Authentication Module (Backend)
&lt;/h3&gt;

&lt;p&gt;The heavy lifting is done at the system level. When Linux requests authentication (e.g., login or &lt;code&gt;sudo&lt;/code&gt;), the Linux Pluggable Authentication Module (PAM) steps in.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Language&lt;/strong&gt;: C++17 for raw performance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Machine Learning&lt;/strong&gt;: &lt;strong&gt;LibTorch&lt;/strong&gt; (PyTorch C++) powers local inference using &lt;strong&gt;YOLO&lt;/strong&gt; (Face Detection), &lt;strong&gt;EdgeFace&lt;/strong&gt; (Recognition), and &lt;strong&gt;MobileNetV3&lt;/strong&gt; (Anti-spoofing).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vision&lt;/strong&gt;: &lt;strong&gt;OpenCV&lt;/strong&gt; handles image and frame processing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security Architecture&lt;/strong&gt;: The PAM module spawns an isolated &lt;code&gt;biopass-helper&lt;/code&gt; process to capture biometrics and perform inference, keeping the core OS auth flow stable and secure.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. The Desktop Management App (Frontend)
&lt;/h3&gt;

&lt;p&gt;Because it's 2026, you shouldn't have to edit YAML configs in &lt;code&gt;vim&lt;/code&gt; just to enroll a fingerprint.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Framework&lt;/strong&gt;: &lt;strong&gt;Tauri v2&lt;/strong&gt; + &lt;strong&gt;Rust&lt;/strong&gt; creates a lightweight, secure bridge between the system calls and the UI.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;UI&lt;/strong&gt;: A blazing fast &lt;strong&gt;Vite + React&lt;/strong&gt; frontend built with &lt;strong&gt;TypeScript&lt;/strong&gt; and styled with &lt;strong&gt;TailwindCSS&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Installation and Setup
&lt;/h2&gt;

&lt;p&gt;Getting started with Biopass is straightforward! We provide pre-built packages for easy installation.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Download the latest release&lt;/strong&gt;: Visit our &lt;a href="https://github.com/TickLabVN/biopass/releases" rel="noopener noreferrer"&gt;Releases page&lt;/a&gt; and download the appropriate package for your distribution (we provide &lt;code&gt;.deb&lt;/code&gt; files for Debian/Ubuntu-based distros).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Install the package&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   &lt;span class="nb"&gt;sudo &lt;/span&gt;dpkg &lt;span class="nt"&gt;-i&lt;/span&gt; biopass_&lt;span class="k"&gt;*&lt;/span&gt;.deb
   &lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="c"&gt;# to resolve any missing dependencies&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Open the Biopass App&lt;/strong&gt;: Launch Biopass from your application menu, set up your face or fingerprint data.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Enjoy seamless logins!&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  What's Next?
&lt;/h2&gt;

&lt;p&gt;We are actively developing Biopass. On our immediate roadmap:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Voice Authentication&lt;/strong&gt;: Recognition and anti-spoofing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Local AI Model Management&lt;/strong&gt;: Download, update, and manage your AI models right from the GUI.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Improve Face Anti-Spoofing&lt;/strong&gt;: Current model is quite inaccurate.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;IR Camera Support&lt;/strong&gt;: Add support for IR cameras for better face recognition.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Try It Out &amp;amp; Get Involved
&lt;/h2&gt;

&lt;p&gt;Biopass is fully open-source and we would absolutely love for the Linux community to try it out, report bugs, and contribute.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Repository&lt;/strong&gt;: &lt;a href="https://github.com/TickLabVN/biopass" rel="noopener noreferrer"&gt;TickLabVN/biopass on GitHub&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Download / Installation&lt;/strong&gt;: Check out our &lt;a href="https://github.com/TickLabVN/biopass/releases" rel="noopener noreferrer"&gt;Latest Release&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Contributing&lt;/strong&gt;: Want to help out? Check our &lt;a href="https://github.com/TickLabVN/biopass/blob/main/docs/contributing.md" rel="noopener noreferrer"&gt;Contributing Guidelines&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>linux</category>
      <category>opensource</category>
      <category>cpp</category>
      <category>security</category>
    </item>
    <item>
      <title>Tonic - Swaggo alternative</title>
      <dc:creator>Nguyễn Phúc Vinh</dc:creator>
      <pubDate>Sat, 17 Feb 2024 03:14:10 +0000</pubDate>
      <link>https://forem.com/phucvinh57/tonic-swaggo-alternative-5a6o</link>
      <guid>https://forem.com/phucvinh57/tonic-swaggo-alternative-5a6o</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;My team just switched my main programming language from JavaScript to Go last month and tried to find an API docs library for our new project..&lt;/p&gt;

&lt;p&gt;But frameworks like &lt;a href="https://github.com/gin-gonic/gin"&gt;Gin&lt;/a&gt; or &lt;a href="https://github.com/labstack/echo"&gt;Echo&lt;/a&gt; do not support it natively like Fastify does. We found &lt;a href="https://github.com/swaggo/swag"&gt;Swaggo&lt;/a&gt;, a wonderful tool, but it's required many steps: writing godocs, then use CLI to gen specs, and finally host swagger UI from specs. We just need a library that directly reflects my structs &amp;amp; routes definitions, then creates a Swagger UI for me, straightforwards and fully automatic.&lt;/p&gt;

&lt;p&gt;Seems like the Go style is design-first approach, it's hard to find a library that meets our needs. So I created a Go lib, named &lt;code&gt;Tonic&lt;/code&gt;, and want to share with community.&lt;/p&gt;

&lt;p&gt;Visit my repo: &lt;a href="https://github.com/TickLabVN/tonic"&gt;https://github.com/TickLabVN/tonic&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;For the first release, Tonic may not support all features of OpenAPI and has some limitations. Welcome all contributions to make Tonic better.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Main ideas
&lt;/h2&gt;

&lt;p&gt;Using the native lib reflect, Tonic reads struct's metadata like JSON tag, data type... and generates an object schema for the struct. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;ArticleDTO&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;ID&lt;/span&gt;      &lt;span class="kt"&gt;int&lt;/span&gt;     &lt;span class="s"&gt;`json:"id"`&lt;/span&gt;
    &lt;span class="n"&gt;Title&lt;/span&gt;   &lt;span class="kt"&gt;string&lt;/span&gt;  &lt;span class="s"&gt;`json:"title" binding:"required,min=4,max=255"`&lt;/span&gt;
    &lt;span class="n"&gt;Content&lt;/span&gt;     &lt;span class="kt"&gt;string&lt;/span&gt;  &lt;span class="s"&gt;`json:"content" binding:"required,min=20"`&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// Will be generated to&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s"&gt;"id: {
        "&lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="s"&gt;": "&lt;/span&gt;&lt;span class="n"&gt;integer&lt;/span&gt;&lt;span class="s"&gt;"
    },
    "&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="s"&gt;": {
        "&lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;"minLength"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;"maxLength"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;255&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="s"&gt;"content"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="s"&gt;"type: "&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="s"&gt;",
        "&lt;/span&gt;&lt;span class="n"&gt;minLength&lt;/span&gt;&lt;span class="s"&gt;": 20
    }
}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Route defintion in Tonic:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;gin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Default&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;rg&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/api"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;tonic&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CreateRoutes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BasePath&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;tonic&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Route&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Method&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Tonic&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;Url&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"/ping"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;HandlerRegister&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;rg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GET&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Ping&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="n"&gt;Schema&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;tonic&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RouteSchema&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;Response&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{}{&lt;/span&gt;
                &lt;span class="m"&gt;200&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;PingResponse&lt;/span&gt;&lt;span class="p"&gt;{},&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After all, Tonic reads all route definitions and JSON schemas generated from structs, constructs all of these pieces of information into a Swagger object at runtime, then uses an external library to host the Swagger UI.&lt;/p&gt;

&lt;p&gt;Tonic is not tightly coupled with any frameworks, developers can easily integrate it with existing projects.&lt;/p&gt;

&lt;h2&gt;
  
  
  Full example with Gin
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;main.go&lt;/code&gt;'s content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/gin-gonic/gin"&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/TickLabVN/tonic"&lt;/span&gt;
    &lt;span class="s"&gt;"net/http"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;PingResponse&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Message&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="s"&gt;`json:"message"`&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;Ping&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;gin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;PingResponse&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"pong"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;gin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Default&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;tonic&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;tonic&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;OpenAPIVersion&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"3.0.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;Info&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{}{&lt;/span&gt;
            &lt;span class="s"&gt;"title"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;       &lt;span class="s"&gt;"Go CRUD Example"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s"&gt;"description"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"A simple CRUD example using Go and PostgreSQL"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s"&gt;"version"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;     &lt;span class="s"&gt;"1.0.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="n"&gt;rg&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/api"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;tonic&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CreateRoutes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BasePath&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;tonic&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Route&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;Method&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;tonic&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;Url&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"/ping"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;HandlerRegister&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;rg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GET&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Ping&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="n"&gt;Schema&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;tonic&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RouteSchema&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;Response&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{}{&lt;/span&gt;
                        &lt;span class="m"&gt;200&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;PingResponse&lt;/span&gt;&lt;span class="p"&gt;{},&lt;/span&gt;
                    &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;// tonic.GetHandler() returns the net/http handler for serving the swagger documentation&lt;/span&gt;
    &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GET&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/docs/*w"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;gin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WrapH&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StripPrefix&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/docs"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tonic&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetHandler&lt;/span&gt;&lt;span class="p"&gt;())))&lt;/span&gt;

    &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;":8080"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Result:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq993ja7o6htmhgru4h4e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq993ja7o6htmhgru4h4e.png" alt="Swagger example" width="800" height="436"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>go</category>
      <category>restapi</category>
      <category>swagger</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
