{"id":1965,"date":"2025-02-27T09:28:36","date_gmt":"2025-02-27T01:28:36","guid":{"rendered":"https:\/\/www.fanyamin.com\/wordpress\/?p=1965"},"modified":"2025-02-27T09:32:56","modified_gmt":"2025-02-27T01:32:56","slug":"best-practice-of-go-backend-service","status":"publish","type":"post","link":"https:\/\/www.fanyamin.com\/wordpress\/?p=1965","title":{"rendered":"best practice of go backend service 1"},"content":{"rendered":"<h2>best practice<\/h2>\n<h3>1. <strong>Project Structure<\/strong><\/h3>\n<p>Organize your project in a logical and consistent way. A common structure for a Go backend service is:<\/p>\n<pre><code>\/my-service\n  \u251c\u2500\u2500 \/cmd\n  \u2502   \u2514\u2500\u2500 \/my-service\n  \u2502       \u2514\u2500\u2500 main.go\n  \u251c\u2500\u2500 \/internal\n  \u2502   \u251c\u2500\u2500 \/handlers\n  \u2502   \u251c\u2500\u2500 \/models\n  \u2502   \u251c\u2500\u2500 \/services\n  \u2502   \u2514\u2500\u2500 \/repositories\n  \u251c\u2500\u2500 \/pkg\n  \u2502   \u2514\u2500\u2500 \/utils\n  \u251c\u2500\u2500 \/configs\n  \u251c\u2500\u2500 \/migrations\n  \u251c\u2500\u2500 \/api\n  \u251c\u2500\u2500 \/scripts\n  \u2514\u2500\u2500 go.mod<\/code><\/pre>\n<ul>\n<li><strong><code>cmd\/my-service\/main.go<\/code><\/strong>: Entry point of your application.<\/li>\n<li><strong><code>internal\/<\/code><\/strong>: Contains the core application logic. This directory is private to your module.<\/li>\n<li><strong><code>pkg\/<\/code><\/strong>: Reusable utility functions or libraries.<\/li>\n<li><strong><code>configs\/<\/code><\/strong>: Configuration files.<\/li>\n<li><strong><code>migrations\/<\/code><\/strong>: Database migration scripts.<\/li>\n<li><strong><code>api\/<\/code><\/strong>: API definitions (e.g., OpenAPI\/Swagger specs).<\/li>\n<li><strong><code>scripts\/<\/code><\/strong>: Helper scripts for deployment, testing, etc.<\/li>\n<\/ul>\n<hr \/>\n<h3>2. <strong>Use Dependency Injection<\/strong><\/h3>\n<p>Avoid global variables and tightly coupled code. Pass dependencies (e.g., database connections, services) explicitly to functions or structs.<\/p>\n<pre><code class=\"language-go\">type UserService struct {\n    repo UserRepository\n}\n\nfunc NewUserService(repo UserRepository) *UserService {\n    return &amp;UserService{repo: repo}\n}\n\nfunc (s *UserService) GetUser(id int) (*User, error) {\n    return s.repo.FindByID(id)\n}<\/code><\/pre>\n<hr \/>\n<h3>3. <strong>Error Handling<\/strong><\/h3>\n<ul>\n<li>Always handle errors explicitly.<\/li>\n<li>Use <code>errors.New<\/code> or <code>fmt.Errorf<\/code> to create meaningful error messages.<\/li>\n<li>Consider using <code>errors.Is<\/code> and <code>errors.As<\/code> for error comparisons and type assertions.<\/li>\n<\/ul>\n<pre><code class=\"language-go\">if err != nil {\n    return fmt.Errorf(&quot;failed to fetch user: %w&quot;, err)\n}<\/code><\/pre>\n<hr \/>\n<h3>4. <strong>Logging<\/strong><\/h3>\n<p>Use a structured logging library like <code>logrus<\/code> or <code>zap<\/code> for better log management.<\/p>\n<pre><code class=\"language-go\">import (\n    &quot;github.com\/sirupsen\/logrus&quot;\n)\n\nfunc main() {\n    log := logrus.New()\n    log.Info(&quot;Starting the application...&quot;)\n}<\/code><\/pre>\n<hr \/>\n<h3>5. <strong>Configuration Management<\/strong><\/h3>\n<p>Use environment variables or configuration files (e.g., JSON, YAML) to manage settings. Libraries like <code>viper<\/code> can help.<\/p>\n<pre><code class=\"language-go\">import (\n    &quot;github.com\/spf13\/viper&quot;\n)\n\nfunc init() {\n    viper.SetConfigFile(&quot;config.yaml&quot;)\n    if err := viper.ReadInConfig(); err != nil {\n        log.Fatalf(&quot;Error reading config file: %v&quot;, err)\n    }\n}<\/code><\/pre>\n<hr \/>\n<h3>6. <strong>Database Access<\/strong><\/h3>\n<ul>\n<li>Use an ORM like <code>gorm<\/code> or a query builder like <code>sqlx<\/code> for database interactions.<\/li>\n<li>Always use prepared statements to avoid SQL injection.<\/li>\n<\/ul>\n<pre><code class=\"language-go\">import (\n    &quot;github.com\/jmoiron\/sqlx&quot;\n    _ &quot;github.com\/lib\/pq&quot;\n)\n\nfunc main() {\n    db, err := sqlx.Connect(&quot;postgres&quot;, &quot;user=postgres dbname=mydb sslmode=disable&quot;)\n    if err != nil {\n        log.Fatalln(err)\n    }\n    defer db.Close()\n}<\/code><\/pre>\n<hr \/>\n<h3>7. <strong>API Design<\/strong><\/h3>\n<ul>\n<li>Use RESTful principles for designing APIs.<\/li>\n<li>Group related routes and use middleware for cross-cutting concerns (e.g., logging, authentication).<\/li>\n<\/ul>\n<pre><code class=\"language-go\">import (\n    &quot;github.com\/gorilla\/mux&quot;\n    &quot;net\/http&quot;\n)\n\nfunc main() {\n    r := mux.NewRouter()\n    r.HandleFunc(&quot;\/users&quot;, GetUsers).Methods(&quot;GET&quot;)\n    r.HandleFunc(&quot;\/users\/{id}&quot;, GetUser).Methods(&quot;GET&quot;)\n    http.ListenAndServe(&quot;:8080&quot;, r)\n}<\/code><\/pre>\n<hr \/>\n<h3>8. <strong>Testing<\/strong><\/h3>\n<ul>\n<li>Write unit tests for your functions and integration tests for your APIs.<\/li>\n<li>Use the <code>testing<\/code> package and tools like <code>testify<\/code> for assertions.<\/li>\n<\/ul>\n<pre><code class=\"language-go\">import (\n    &quot;testing&quot;\n    &quot;github.com\/stretchr\/testify\/assert&quot;\n)\n\nfunc TestAdd(t *testing.T) {\n    result := Add(2, 3)\n    assert.Equal(t, 5, result)\n}<\/code><\/pre>\n<hr \/>\n<h3>9. <strong>Concurrency<\/strong><\/h3>\n<p>Leverage Go's concurrency primitives (<code>goroutines<\/code> and <code>channels<\/code>) for tasks that can run in parallel.<\/p>\n<pre><code class=\"language-go\">func process(data chan int) {\n    for d := range data {\n        fmt.Println(&quot;Processing:&quot;, d)\n    }\n}\n\nfunc main() {\n    data := make(chan int)\n    go process(data)\n\n    for i := 0; i &lt; 10; i++ {\n        data &lt;- i\n    }\n    close(data)\n}<\/code><\/pre>\n<hr \/>\n<h3>10. <strong>Graceful Shutdown<\/strong><\/h3>\n<p>Handle shutdown signals to clean up resources (e.g., database connections) before exiting.<\/p>\n<pre><code class=\"language-go\">import (\n    &quot;context&quot;\n    &quot;net\/http&quot;\n    &quot;os&quot;\n    &quot;os\/signal&quot;\n    &quot;syscall&quot;\n    &quot;time&quot;\n)\n\nfunc main() {\n    server := &amp;http.Server{Addr: &quot;:8080&quot;}\n\n    go func() {\n        if err := server.ListenAndServe(); err != nil &amp;&amp; err != http.ErrServerClosed {\n            log.Fatalf(&quot;Server error: %v&quot;, err)\n        }\n    }()\n\n    quit := make(chan os.Signal, 1)\n    signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)\n    &lt;-quit\n\n    ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)\n    defer cancel()\n\n    if err := server.Shutdown(ctx); err != nil {\n        log.Fatalf(&quot;Server shutdown error: %v&quot;, err)\n    }\n}<\/code><\/pre>\n<hr \/>\n<h3>11. <strong>Documentation<\/strong><\/h3>\n<ul>\n<li>Use Go's built-in documentation tool (<code>go doc<\/code>) to document your code.<\/li>\n<li>Write clear and concise comments for exported functions, types, and packages.<\/li>\n<\/ul>\n<pre><code class=\"language-go\">\/\/ Add adds two integers and returns the result.\nfunc Add(a, b int) int {\n    return a + b\n}<\/code><\/pre>\n<hr \/>\n<h3>12. <strong>Versioning<\/strong><\/h3>\n<p>Use semantic versioning for your APIs and libraries. For example:<\/p>\n<pre><code>\/v1\/users\n\/v2\/users<\/code><\/pre>\n<hr \/>\n<h3>13. <strong>Use Linters and Formatters<\/strong><\/h3>\n<ul>\n<li>Use <code>gofmt<\/code> to format your code.<\/li>\n<li>Use <code>golint<\/code> or <code>golangci-lint<\/code> to enforce coding standards.<\/li>\n<\/ul>\n<hr \/>\n<h3>14. <strong>Monitor and Profile<\/strong><\/h3>\n<ul>\n<li>Use tools like <code>pprof<\/code> for profiling your application.<\/li>\n<li>Monitor performance and resource usage in production.<\/li>\n<\/ul>\n<hr \/>\n<p>By following these best practices, you can build robust, maintainable, and scalable backend services in Go. Happy coding! \ud83d\ude80<\/p>\n","protected":false},"excerpt":{"rendered":"<p>best practice 1. Project Structure Organize your project in a logical and consistent way. A common structure for a Go backend service is: \/my-service \u251c\u2500\u2500 \/cmd \u2502 \u2514\u2500\u2500 \/my-service \u2502 \u2514\u2500\u2500 main.go \u251c\u2500\u2500 \/internal \u2502 \u251c\u2500\u2500 \/handlers \u2502 \u251c\u2500\u2500 \/models \u2502 \u251c\u2500\u2500 \/services \u2502 \u2514\u2500\u2500 \/repositories \u251c\u2500\u2500 \/pkg \u2502 \u2514\u2500\u2500 \/utils \u251c\u2500\u2500 \/configs \u251c\u2500\u2500 \/migrations [&hellip;] <a class=\"read-more\" href=\"https:\/\/www.fanyamin.com\/wordpress\/?p=1965\" title=\"Permanent Link to: best practice of go backend service 1\">&rarr;Read&nbsp;more<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[22],"tags":[],"class_list":["post-1965","post","type-post","status-publish","format-standard","hentry","category-golang"],"_links":{"self":[{"href":"https:\/\/www.fanyamin.com\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/1965"}],"collection":[{"href":"https:\/\/www.fanyamin.com\/wordpress\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.fanyamin.com\/wordpress\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.fanyamin.com\/wordpress\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.fanyamin.com\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1965"}],"version-history":[{"count":2,"href":"https:\/\/www.fanyamin.com\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/1965\/revisions"}],"predecessor-version":[{"id":1967,"href":"https:\/\/www.fanyamin.com\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/1965\/revisions\/1967"}],"wp:attachment":[{"href":"https:\/\/www.fanyamin.com\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1965"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.fanyamin.com\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1965"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.fanyamin.com\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1965"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}