@ngxtm/devkit 3.4.0 → 3.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -1
- package/rules/README.md +141 -0
- package/rules/dart/best-practices/SKILL.md +23 -0
- package/rules/dart/language/SKILL.md +52 -0
- package/rules/dart/tooling/SKILL.md +43 -0
- package/rules/dotnet/aspnet-core/SKILL.md +92 -0
- package/rules/dotnet/aspnet-core/references/REFERENCE.md +335 -0
- package/rules/dotnet/best-practices/SKILL.md +101 -0
- package/rules/dotnet/best-practices/references/REFERENCE.md +256 -0
- package/rules/dotnet/blazor/SKILL.md +146 -0
- package/rules/dotnet/blazor/references/REFERENCE.md +392 -0
- package/rules/dotnet/language/SKILL.md +82 -0
- package/rules/dotnet/language/references/REFERENCE.md +222 -0
- package/rules/dotnet/patterns.rule.md +388 -0
- package/rules/dotnet/razor-pages/SKILL.md +124 -0
- package/rules/dotnet/razor-pages/references/REFERENCE.md +321 -0
- package/rules/dotnet/security/SKILL.md +89 -0
- package/rules/dotnet/security/references/REFERENCE.md +295 -0
- package/rules/dotnet/tooling/SKILL.md +92 -0
- package/rules/dotnet/tooling/references/REFERENCE.md +300 -0
- package/rules/flutter/auto-route-navigation/SKILL.md +43 -0
- package/rules/flutter/auto-route-navigation/references/REFERENCE.md +19 -0
- package/rules/flutter/auto-route-navigation/references/router-config.md +62 -0
- package/rules/flutter/bloc-state-management/SKILL.md +64 -0
- package/rules/flutter/bloc-state-management/references/REFERENCE.md +20 -0
- package/rules/flutter/bloc-state-management/references/auth-bloc-example.md +52 -0
- package/rules/flutter/bloc-state-management/references/equatable-usage.md +56 -0
- package/rules/flutter/bloc-state-management/references/property-based-state.md +68 -0
- package/rules/flutter/bloc.rule.md +76 -0
- package/rules/flutter/cicd/SKILL.md +48 -0
- package/rules/flutter/cicd/references/advanced-workflow.md +66 -0
- package/rules/flutter/cicd/references/fastlane.md +139 -0
- package/rules/flutter/cicd/references/github-actions.md +59 -0
- package/rules/flutter/dependency-injection/SKILL.md +42 -0
- package/rules/flutter/dependency-injection/references/REFERENCE.md +15 -0
- package/rules/flutter/dependency-injection/references/modules.md +37 -0
- package/rules/flutter/error-handling/SKILL.md +32 -0
- package/rules/flutter/error-handling/references/REFERENCE.md +19 -0
- package/rules/flutter/error-handling/references/error-mapping.md +31 -0
- package/rules/flutter/feature-based-clean-architecture/SKILL.md +46 -0
- package/rules/flutter/feature-based-clean-architecture/references/REFERENCE.md +14 -0
- package/rules/flutter/feature-based-clean-architecture/references/folder-structure.md +36 -0
- package/rules/flutter/getx-navigation/SKILL.md +70 -0
- package/rules/flutter/getx-navigation/references/app-pages.md +40 -0
- package/rules/flutter/getx-navigation/references/middleware-example.md +29 -0
- package/rules/flutter/getx-state-management/SKILL.md +76 -0
- package/rules/flutter/getx-state-management/references/binding-example.md +32 -0
- package/rules/flutter/getx-state-management/references/reactive-vs-simple.md +39 -0
- package/rules/flutter/go-router-navigation/SKILL.md +57 -0
- package/rules/flutter/idiomatic-flutter/SKILL.md +20 -0
- package/rules/flutter/layer-based-clean-architecture/SKILL.md +50 -0
- package/rules/flutter/layer-based-clean-architecture/references/REFERENCE.md +60 -0
- package/rules/flutter/layer-based-clean-architecture/references/repository-mapping.md +50 -0
- package/rules/flutter/localization/SKILL.md +50 -0
- package/rules/flutter/localization/references/REFERENCE.md +48 -0
- package/rules/flutter/localization/references/sheet-loader.md +33 -0
- package/rules/flutter/navigator-v1-navigation/SKILL.md +71 -0
- package/rules/flutter/navigator-v1-navigation/references/on-generate-route.md +48 -0
- package/rules/flutter/performance/SKILL.md +24 -0
- package/rules/flutter/retrofit-networking/SKILL.md +51 -0
- package/rules/flutter/retrofit-networking/references/REFERENCE.md +19 -0
- package/rules/flutter/retrofit-networking/references/token-refresh.md +40 -0
- package/rules/flutter/riverpod-state-management/SKILL.md +53 -0
- package/rules/flutter/riverpod-state-management/references/architecture.md +124 -0
- package/rules/flutter/riverpod-state-management/references/best-practices.md +89 -0
- package/rules/flutter/riverpod-state-management/references/testing.md +73 -0
- package/rules/flutter/riverpod.rule.md +78 -0
- package/rules/flutter/security/SKILL.md +33 -0
- package/rules/flutter/security/references/REFERENCE.md +15 -0
- package/rules/flutter/security/references/network-security.md +28 -0
- package/rules/flutter/testing/SKILL.md +44 -0
- package/rules/flutter/testing/references/REFERENCE.md +21 -0
- package/rules/flutter/testing/references/bloc-testing.md +38 -0
- package/rules/flutter/testing/references/integration-testing.md +128 -0
- package/rules/flutter/testing/references/robot-pattern.md +82 -0
- package/rules/flutter/testing/references/unit-testing.md +130 -0
- package/rules/flutter/testing/references/widget-testing.md +120 -0
- package/rules/flutter/widgets/SKILL.md +37 -0
- package/rules/golang/chi-router/SKILL.md +219 -0
- package/rules/golang/chi-router/references/REFERENCE.md +13 -0
- package/rules/golang/chi-router/references/routing-patterns.md +205 -0
- package/rules/golang/cobra-cli/SKILL.md +227 -0
- package/rules/golang/cobra-cli/references/REFERENCE.md +13 -0
- package/rules/golang/cobra-cli/references/command-patterns.md +224 -0
- package/rules/golang/core/SKILL.md +210 -0
- package/rules/golang/core/references/REFERENCE.md +14 -0
- package/rules/golang/core/references/concurrency-patterns.md +114 -0
- package/rules/golang/core/references/error-handling.md +87 -0
- package/rules/golang/echo-framework/SKILL.md +215 -0
- package/rules/golang/echo-framework/references/REFERENCE.md +14 -0
- package/rules/golang/echo-framework/references/middleware-patterns.md +141 -0
- package/rules/golang/echo-framework/references/routing-patterns.md +140 -0
- package/rules/golang/ent-orm/SKILL.md +239 -0
- package/rules/golang/ent-orm/references/REFERENCE.md +13 -0
- package/rules/golang/ent-orm/references/schema-patterns.md +255 -0
- package/rules/golang/fiber-framework/SKILL.md +196 -0
- package/rules/golang/fiber-framework/references/REFERENCE.md +13 -0
- package/rules/golang/fiber-framework/references/routing-patterns.md +191 -0
- package/rules/golang/gin-framework/SKILL.md +205 -0
- package/rules/golang/gin-framework/references/REFERENCE.md +14 -0
- package/rules/golang/gin-framework/references/middleware-patterns.md +119 -0
- package/rules/golang/gorm-orm/SKILL.md +196 -0
- package/rules/golang/gorm-orm/references/REFERENCE.md +14 -0
- package/rules/golang/gorm-orm/references/model-definitions.md +167 -0
- package/rules/golang/gorm-orm/references/query-patterns.md +161 -0
- package/rules/golang/grpc/SKILL.md +231 -0
- package/rules/golang/grpc/references/REFERENCE.md +13 -0
- package/rules/golang/grpc/references/service-patterns.md +276 -0
- package/rules/golang/testify/SKILL.md +239 -0
- package/rules/golang/testify/references/REFERENCE.md +13 -0
- package/rules/golang/testify/references/assert-patterns.md +170 -0
- package/rules/golang/validator/SKILL.md +234 -0
- package/rules/golang/validator/references/REFERENCE.md +13 -0
- package/rules/golang/validator/references/validation-tags.md +211 -0
- package/rules/golang/viper-config/SKILL.md +244 -0
- package/rules/golang/viper-config/references/REFERENCE.md +13 -0
- package/rules/golang/viper-config/references/config-loading.md +181 -0
- package/rules/golang/wire-di/SKILL.md +243 -0
- package/rules/golang/wire-di/references/REFERENCE.md +13 -0
- package/rules/golang/wire-di/references/provider-patterns.md +193 -0
- package/rules/golang/zap-logging/SKILL.md +203 -0
- package/rules/golang/zap-logging/references/REFERENCE.md +13 -0
- package/rules/golang/zap-logging/references/logger-config.md +165 -0
- package/rules/java/build-gradle/SKILL.md +92 -0
- package/rules/java/build-gradle/references/REFERENCE.md +14 -0
- package/rules/java/build-gradle/references/kotlin-dsl.md +118 -0
- package/rules/java/build-gradle/references/task-configuration.md +132 -0
- package/rules/java/build-maven/SKILL.md +86 -0
- package/rules/java/build-maven/references/REFERENCE.md +14 -0
- package/rules/java/build-maven/references/dependency-management.md +111 -0
- package/rules/java/build-maven/references/lifecycle-phases.md +114 -0
- package/rules/java/graalvm-native/SKILL.md +105 -0
- package/rules/java/graalvm-native/references/REFERENCE.md +12 -0
- package/rules/java/java-collections-streams/SKILL.md +148 -0
- package/rules/java/java-collections-streams/references/REFERENCE.md +15 -0
- package/rules/java/java-collections-streams/references/collectors-patterns.md +178 -0
- package/rules/java/java-collections-streams/references/stream-pipelines.md +165 -0
- package/rules/java/java-concurrency/SKILL.md +187 -0
- package/rules/java/java-concurrency/references/REFERENCE.md +17 -0
- package/rules/java/java-concurrency/references/completable-future.md +165 -0
- package/rules/java/java-concurrency/references/executor-patterns.md +176 -0
- package/rules/java/java-concurrency/references/virtual-threads.md +190 -0
- package/rules/java/java-core-language/SKILL.md +121 -0
- package/rules/java/java-core-language/references/REFERENCE.md +15 -0
- package/rules/java/java-core-language/references/jvm-memory-model.md +160 -0
- package/rules/java/java-core-language/references/modern-java-features.md +168 -0
- package/rules/java/java-project-structure/SKILL.md +195 -0
- package/rules/java/java-project-structure/references/REFERENCE.md +15 -0
- package/rules/java/java-project-structure/references/maven-project-layout.md +199 -0
- package/rules/java/java-project-structure/references/module-system.md +159 -0
- package/rules/java/micronaut-core/SKILL.md +99 -0
- package/rules/java/micronaut-core/references/REFERENCE.md +12 -0
- package/rules/java/micronaut-reactive/SKILL.md +68 -0
- package/rules/java/micronaut-reactive/references/REFERENCE.md +12 -0
- package/rules/java/quarkus-core/SKILL.md +85 -0
- package/rules/java/quarkus-core/references/REFERENCE.md +12 -0
- package/rules/java/quarkus-reactive/SKILL.md +67 -0
- package/rules/java/quarkus-reactive/references/REFERENCE.md +12 -0
- package/rules/java/spring-batch/SKILL.md +102 -0
- package/rules/java/spring-batch/references/REFERENCE.md +12 -0
- package/rules/java/spring-boot-architecture/SKILL.md +206 -0
- package/rules/java/spring-boot-architecture/references/REFERENCE.md +15 -0
- package/rules/java/spring-boot-architecture/references/auto-configuration.md +158 -0
- package/rules/java/spring-boot-architecture/references/configuration-properties.md +202 -0
- package/rules/java/spring-boot-web/SKILL.md +217 -0
- package/rules/java/spring-boot-web/references/REFERENCE.md +17 -0
- package/rules/java/spring-cloud/SKILL.md +109 -0
- package/rules/java/spring-cloud/references/REFERENCE.md +13 -0
- package/rules/java/spring-data-jpa/SKILL.md +241 -0
- package/rules/java/spring-data-jpa/references/REFERENCE.md +16 -0
- package/rules/java/spring-security/SKILL.md +161 -0
- package/rules/java/spring-security/references/REFERENCE.md +16 -0
- package/rules/java/spring-security/references/jwt-auth-flow.md +213 -0
- package/rules/java/testing-junit-mockito/SKILL.md +135 -0
- package/rules/java/testing-junit-mockito/references/REFERENCE.md +15 -0
- package/rules/java/testing-junit-mockito/references/junit5-patterns.md +159 -0
- package/rules/java/testing-junit-mockito/references/mockito-patterns.md +148 -0
- package/rules/java/testing-junit-mockito/references/spring-boot-testing.md +152 -0
- package/rules/javascript/best-practices/SKILL.md +64 -0
- package/rules/javascript/best-practices/references/REFERENCE.md +91 -0
- package/rules/javascript/language/SKILL.md +71 -0
- package/rules/javascript/language/references/REFERENCE.md +106 -0
- package/rules/javascript/tooling/SKILL.md +60 -0
- package/rules/javascript/tooling/references/REFERENCE.md +107 -0
- package/rules/metadata.json +54 -0
- package/rules/nestjs/api-standards/SKILL.md +47 -0
- package/rules/nestjs/api-standards/references/pagination-wrapper.md +87 -0
- package/rules/nestjs/architecture/SKILL.md +68 -0
- package/rules/nestjs/architecture/references/dynamic-module.md +53 -0
- package/rules/nestjs/caching/SKILL.md +51 -0
- package/rules/nestjs/caching/references/REFERENCE.md +13 -0
- package/rules/nestjs/caching/references/cache-patterns.md +183 -0
- package/rules/nestjs/configuration/SKILL.md +41 -0
- package/rules/nestjs/configuration/references/REFERENCE.md +13 -0
- package/rules/nestjs/configuration/references/config-patterns.md +184 -0
- package/rules/nestjs/controllers-services/SKILL.md +63 -0
- package/rules/nestjs/controllers-services/references/REFERENCE.md +14 -0
- package/rules/nestjs/controllers-services/references/controller-patterns.md +119 -0
- package/rules/nestjs/controllers-services/references/service-patterns.md +129 -0
- package/rules/nestjs/database/SKILL.md +102 -0
- package/rules/nestjs/database/references/REFERENCE.md +14 -0
- package/rules/nestjs/database/references/typeorm-patterns.md +156 -0
- package/rules/nestjs/deployment/SKILL.md +36 -0
- package/rules/nestjs/deployment/references/REFERENCE.md +13 -0
- package/rules/nestjs/deployment/references/deployment-patterns.md +140 -0
- package/rules/nestjs/documentation/SKILL.md +64 -0
- package/rules/nestjs/documentation/references/REFERENCE.md +13 -0
- package/rules/nestjs/documentation/references/swagger-patterns.md +139 -0
- package/rules/nestjs/error-handling/SKILL.md +55 -0
- package/rules/nestjs/error-handling/references/REFERENCE.md +13 -0
- package/rules/nestjs/error-handling/references/exception-filters.md +152 -0
- package/rules/nestjs/file-uploads/SKILL.md +35 -0
- package/rules/nestjs/file-uploads/references/REFERENCE.md +13 -0
- package/rules/nestjs/file-uploads/references/upload-patterns.md +125 -0
- package/rules/nestjs/observability/SKILL.md +39 -0
- package/rules/nestjs/observability/references/REFERENCE.md +13 -0
- package/rules/nestjs/observability/references/logging-metrics.md +175 -0
- package/rules/nestjs/performance/SKILL.md +60 -0
- package/rules/nestjs/performance/references/REFERENCE.md +13 -0
- package/rules/nestjs/performance/references/performance-patterns.md +107 -0
- package/rules/nestjs/real-time/SKILL.md +45 -0
- package/rules/nestjs/real-time/references/REFERENCE.md +13 -0
- package/rules/nestjs/real-time/references/websocket-patterns.md +121 -0
- package/rules/nestjs/scheduling/SKILL.md +39 -0
- package/rules/nestjs/scheduling/references/REFERENCE.md +13 -0
- package/rules/nestjs/scheduling/references/scheduling-patterns.md +137 -0
- package/rules/nestjs/search/SKILL.md +41 -0
- package/rules/nestjs/search/references/REFERENCE.md +13 -0
- package/rules/nestjs/search/references/search-patterns.md +137 -0
- package/rules/nestjs/security/SKILL.md +87 -0
- package/rules/nestjs/security/references/REFERENCE.md +14 -0
- package/rules/nestjs/security/references/authentication.md +151 -0
- package/rules/nestjs/testing/SKILL.md +40 -0
- package/rules/nestjs/testing/references/REFERENCE.md +14 -0
- package/rules/nestjs/testing/references/unit-testing.md +179 -0
- package/rules/nestjs/transport/SKILL.md +45 -0
- package/rules/nestjs/transport/references/REFERENCE.md +13 -0
- package/rules/nestjs/transport/references/microservices-patterns.md +170 -0
- package/rules/nextjs/app-router/SKILL.md +46 -0
- package/rules/nextjs/app-router/references/REFERENCE.md +14 -0
- package/rules/nextjs/app-router/references/routing-patterns.md +182 -0
- package/rules/nextjs/architecture/SKILL.md +44 -0
- package/rules/nextjs/architecture/references/fsd-structure.md +77 -0
- package/rules/nextjs/authentication/SKILL.md +29 -0
- package/rules/nextjs/authentication/references/auth-implementation.md +73 -0
- package/rules/nextjs/caching/SKILL.md +66 -0
- package/rules/nextjs/caching/references/REFERENCE.md +13 -0
- package/rules/nextjs/caching/references/cache-strategies.md +168 -0
- package/rules/nextjs/data-access-layer/SKILL.md +33 -0
- package/rules/nextjs/data-access-layer/references/patterns.md +66 -0
- package/rules/nextjs/data-fetching/SKILL.md +59 -0
- package/rules/nextjs/data-fetching/references/REFERENCE.md +13 -0
- package/rules/nextjs/data-fetching/references/fetch-patterns.md +160 -0
- package/rules/nextjs/internationalization/SKILL.md +105 -0
- package/rules/nextjs/internationalization/references/REFERENCE.md +13 -0
- package/rules/nextjs/internationalization/references/i18n-patterns.md +180 -0
- package/rules/nextjs/optimization/SKILL.md +64 -0
- package/rules/nextjs/optimization/references/REFERENCE.md +13 -0
- package/rules/nextjs/optimization/references/optimization-patterns.md +190 -0
- package/rules/nextjs/rendering/SKILL.md +91 -0
- package/rules/nextjs/rendering/references/REFERENCE.md +13 -0
- package/rules/nextjs/rendering/references/rendering-modes.md +163 -0
- package/rules/nextjs/server-actions/SKILL.md +46 -0
- package/rules/nextjs/server-actions/references/REFERENCE.md +13 -0
- package/rules/nextjs/server-actions/references/action-patterns.md +188 -0
- package/rules/nextjs/server-components/SKILL.md +52 -0
- package/rules/nextjs/server-components/references/REFERENCE.md +13 -0
- package/rules/nextjs/server-components/references/component-patterns.md +175 -0
- package/rules/nextjs/state-management/SKILL.md +73 -0
- package/rules/nextjs/state-management/references/REFERENCE.md +13 -0
- package/rules/nextjs/state-management/references/state-patterns.md +218 -0
- package/rules/nextjs/styling/SKILL.md +31 -0
- package/rules/nextjs/styling/references/implementation.md +56 -0
- package/rules/react/component-patterns/SKILL.md +66 -0
- package/rules/react/component-patterns/references/REFERENCE.md +126 -0
- package/rules/react/hooks/SKILL.md +60 -0
- package/rules/react/hooks/references/REFERENCE.md +132 -0
- package/rules/react/hooks.rule.md +79 -0
- package/rules/react/performance/SKILL.md +69 -0
- package/rules/react/performance/references/REFERENCE.md +143 -0
- package/rules/react/security/SKILL.md +46 -0
- package/rules/react/security/references/REFERENCE.md +170 -0
- package/rules/react/state-management/SKILL.md +56 -0
- package/rules/react/state-management/references/REFERENCE.md +137 -0
- package/rules/react/testing/SKILL.md +45 -0
- package/rules/react/testing/references/REFERENCE.md +149 -0
- package/rules/react/tooling/SKILL.md +39 -0
- package/rules/react/typescript/SKILL.md +53 -0
- package/rules/rust/actix-web/SKILL.md +160 -0
- package/rules/rust/actix-web/references/REFERENCE.md +13 -0
- package/rules/rust/actix-web/references/handler-patterns.md +198 -0
- package/rules/rust/async-graphql/SKILL.md +228 -0
- package/rules/rust/async-graphql/references/REFERENCE.md +13 -0
- package/rules/rust/async-graphql/references/schema-patterns.md +215 -0
- package/rules/rust/axum/SKILL.md +161 -0
- package/rules/rust/axum/references/REFERENCE.md +14 -0
- package/rules/rust/axum/references/handler-patterns.md +97 -0
- package/rules/rust/bevy/SKILL.md +206 -0
- package/rules/rust/bevy/references/REFERENCE.md +13 -0
- package/rules/rust/bevy/references/ecs-patterns.md +226 -0
- package/rules/rust/clap/SKILL.md +217 -0
- package/rules/rust/clap/references/REFERENCE.md +13 -0
- package/rules/rust/clap/references/derive-patterns.md +205 -0
- package/rules/rust/core/SKILL.md +154 -0
- package/rules/rust/core/references/REFERENCE.md +14 -0
- package/rules/rust/core/references/error-handling.md +92 -0
- package/rules/rust/diesel-orm/SKILL.md +176 -0
- package/rules/rust/diesel-orm/references/REFERENCE.md +13 -0
- package/rules/rust/diesel-orm/references/schema-patterns.md +206 -0
- package/rules/rust/rocket/SKILL.md +182 -0
- package/rules/rust/rocket/references/REFERENCE.md +13 -0
- package/rules/rust/rocket/references/handler-patterns.md +209 -0
- package/rules/rust/sea-orm/SKILL.md +230 -0
- package/rules/rust/sea-orm/references/REFERENCE.md +13 -0
- package/rules/rust/sea-orm/references/entity-patterns.md +221 -0
- package/rules/rust/serde-serialization/SKILL.md +150 -0
- package/rules/rust/serde-serialization/references/REFERENCE.md +13 -0
- package/rules/rust/serde-serialization/references/serialization-patterns.md +199 -0
- package/rules/rust/sqlx-database/SKILL.md +140 -0
- package/rules/rust/sqlx-database/references/REFERENCE.md +13 -0
- package/rules/rust/sqlx-database/references/query-patterns.md +210 -0
- package/rules/rust/tauri/SKILL.md +180 -0
- package/rules/rust/tauri/references/REFERENCE.md +13 -0
- package/rules/rust/tauri/references/command-patterns.md +209 -0
- package/rules/rust/tokio-runtime/SKILL.md +167 -0
- package/rules/rust/tokio-runtime/references/REFERENCE.md +14 -0
- package/rules/rust/tokio-runtime/references/async-patterns.md +137 -0
- package/rules/rust/tokio-runtime/references/synchronization.md +152 -0
- package/rules/rust/tonic/SKILL.md +231 -0
- package/rules/rust/tonic/references/REFERENCE.md +13 -0
- package/rules/rust/tonic/references/service-patterns.md +213 -0
- package/rules/rust/tracing/SKILL.md +214 -0
- package/rules/rust/tracing/references/REFERENCE.md +13 -0
- package/rules/rust/tracing/references/instrumentation.md +187 -0
- package/rules/typescript/best-practices/SKILL.md +108 -0
- package/rules/typescript/best-practices/references/REFERENCE.md +68 -0
- package/rules/typescript/language/SKILL.md +72 -0
- package/rules/typescript/language/references/REFERENCE.md +67 -0
- package/rules/typescript/patterns.rule.md +85 -0
- package/rules/typescript/security/SKILL.md +59 -0
- package/rules/typescript/security/references/REFERENCE.md +113 -0
- package/rules/typescript/tooling/SKILL.md +52 -0
- package/rules/typescript/tooling/references/REFERENCE.md +110 -0
- package/skills/learn/SKILL.md +476 -0
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
# Cobra Command Patterns
|
|
2
|
+
|
|
3
|
+
## Basic Structure
|
|
4
|
+
|
|
5
|
+
```go
|
|
6
|
+
package cmd
|
|
7
|
+
|
|
8
|
+
import (
|
|
9
|
+
"fmt"
|
|
10
|
+
"os"
|
|
11
|
+
"github.com/spf13/cobra"
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
var rootCmd = &cobra.Command{
|
|
15
|
+
Use: "myapp",
|
|
16
|
+
Short: "A brief description of your application",
|
|
17
|
+
Long: `A longer description that spans multiple lines
|
|
18
|
+
and likely contains examples and usage of using your application.`,
|
|
19
|
+
Run: func(cmd *cobra.Command, args []string) {
|
|
20
|
+
// Root command logic (or show help)
|
|
21
|
+
},
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
func Execute() {
|
|
25
|
+
if err := rootCmd.Execute(); err != nil {
|
|
26
|
+
fmt.Fprintln(os.Stderr, err)
|
|
27
|
+
os.Exit(1)
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
func init() {
|
|
32
|
+
// Initialize flags and configuration
|
|
33
|
+
cobra.OnInitialize(initConfig)
|
|
34
|
+
|
|
35
|
+
// Persistent flags (available to this command and all subcommands)
|
|
36
|
+
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file")
|
|
37
|
+
rootCmd.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, "verbose output")
|
|
38
|
+
|
|
39
|
+
// Local flags (only for this command)
|
|
40
|
+
rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
|
|
41
|
+
}
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Subcommands
|
|
45
|
+
|
|
46
|
+
```go
|
|
47
|
+
package cmd
|
|
48
|
+
|
|
49
|
+
import (
|
|
50
|
+
"fmt"
|
|
51
|
+
"github.com/spf13/cobra"
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
var createCmd = &cobra.Command{
|
|
55
|
+
Use: "create [name]",
|
|
56
|
+
Short: "Create a new resource",
|
|
57
|
+
Long: `Create a new resource with the specified name.`,
|
|
58
|
+
Args: cobra.ExactArgs(1), // Require exactly 1 argument
|
|
59
|
+
RunE: func(cmd *cobra.Command, args []string) error {
|
|
60
|
+
name := args[0]
|
|
61
|
+
|
|
62
|
+
// Get flag values
|
|
63
|
+
dryRun, _ := cmd.Flags().GetBool("dry-run")
|
|
64
|
+
template, _ := cmd.Flags().GetString("template")
|
|
65
|
+
|
|
66
|
+
if dryRun {
|
|
67
|
+
fmt.Printf("Would create: %s\n", name)
|
|
68
|
+
return nil
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return createResource(name, template)
|
|
72
|
+
},
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
func init() {
|
|
76
|
+
rootCmd.AddCommand(createCmd)
|
|
77
|
+
|
|
78
|
+
createCmd.Flags().BoolP("dry-run", "n", false, "Dry run mode")
|
|
79
|
+
createCmd.Flags().StringP("template", "t", "default", "Template to use")
|
|
80
|
+
createCmd.MarkFlagRequired("template")
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Argument Validation
|
|
85
|
+
|
|
86
|
+
```go
|
|
87
|
+
var cmd = &cobra.Command{
|
|
88
|
+
Use: "process [file...]",
|
|
89
|
+
Short: "Process files",
|
|
90
|
+
// Argument validators
|
|
91
|
+
Args: cobra.MinimumNArgs(1), // At least 1
|
|
92
|
+
// Args: cobra.MaximumNArgs(3), // At most 3
|
|
93
|
+
// Args: cobra.ExactArgs(2), // Exactly 2
|
|
94
|
+
// Args: cobra.RangeArgs(1, 3), // 1 to 3
|
|
95
|
+
// Args: cobra.NoArgs, // None allowed
|
|
96
|
+
|
|
97
|
+
// Custom validator
|
|
98
|
+
Args: func(cmd *cobra.Command, args []string) error {
|
|
99
|
+
for _, arg := range args {
|
|
100
|
+
if !isValidFile(arg) {
|
|
101
|
+
return fmt.Errorf("invalid file: %s", arg)
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return nil
|
|
105
|
+
},
|
|
106
|
+
|
|
107
|
+
RunE: func(cmd *cobra.Command, args []string) error {
|
|
108
|
+
for _, file := range args {
|
|
109
|
+
if err := processFile(file); err != nil {
|
|
110
|
+
return err
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return nil
|
|
114
|
+
},
|
|
115
|
+
}
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## Flag Types
|
|
119
|
+
|
|
120
|
+
```go
|
|
121
|
+
var (
|
|
122
|
+
stringFlag string
|
|
123
|
+
intFlag int
|
|
124
|
+
boolFlag bool
|
|
125
|
+
stringSlice []string
|
|
126
|
+
stringToString map[string]string
|
|
127
|
+
durationFlag time.Duration
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
func init() {
|
|
131
|
+
// String
|
|
132
|
+
cmd.Flags().StringVarP(&stringFlag, "name", "n", "default", "Description")
|
|
133
|
+
|
|
134
|
+
// Int
|
|
135
|
+
cmd.Flags().IntVarP(&intFlag, "count", "c", 10, "Number of items")
|
|
136
|
+
|
|
137
|
+
// Bool
|
|
138
|
+
cmd.Flags().BoolVarP(&boolFlag, "verbose", "v", false, "Enable verbose")
|
|
139
|
+
|
|
140
|
+
// String slice (can be specified multiple times)
|
|
141
|
+
cmd.Flags().StringSliceVarP(&stringSlice, "tag", "t", nil, "Tags")
|
|
142
|
+
|
|
143
|
+
// String to string map
|
|
144
|
+
cmd.Flags().StringToStringVar(&stringToString, "label", nil, "Labels (key=value)")
|
|
145
|
+
|
|
146
|
+
// Duration
|
|
147
|
+
cmd.Flags().DurationVar(&durationFlag, "timeout", 30*time.Second, "Timeout")
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
## Hooks
|
|
152
|
+
|
|
153
|
+
```go
|
|
154
|
+
var cmd = &cobra.Command{
|
|
155
|
+
Use: "deploy",
|
|
156
|
+
|
|
157
|
+
// Runs before Run
|
|
158
|
+
PreRunE: func(cmd *cobra.Command, args []string) error {
|
|
159
|
+
return validateConfig()
|
|
160
|
+
},
|
|
161
|
+
|
|
162
|
+
// Main execution
|
|
163
|
+
RunE: func(cmd *cobra.Command, args []string) error {
|
|
164
|
+
return deploy()
|
|
165
|
+
},
|
|
166
|
+
|
|
167
|
+
// Runs after Run (even if Run errors)
|
|
168
|
+
PostRunE: func(cmd *cobra.Command, args []string) error {
|
|
169
|
+
return cleanup()
|
|
170
|
+
},
|
|
171
|
+
|
|
172
|
+
// Persistent versions run for all child commands too
|
|
173
|
+
PersistentPreRun: func(cmd *cobra.Command, args []string) {
|
|
174
|
+
initLogging()
|
|
175
|
+
},
|
|
176
|
+
}
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
## Nested Commands
|
|
180
|
+
|
|
181
|
+
```go
|
|
182
|
+
// rootCmd → userCmd → createUserCmd
|
|
183
|
+
var userCmd = &cobra.Command{
|
|
184
|
+
Use: "user",
|
|
185
|
+
Short: "User management",
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
var createUserCmd = &cobra.Command{
|
|
189
|
+
Use: "create [name]",
|
|
190
|
+
Short: "Create a user",
|
|
191
|
+
RunE: func(cmd *cobra.Command, args []string) error {
|
|
192
|
+
return createUser(args[0])
|
|
193
|
+
},
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
var listUserCmd = &cobra.Command{
|
|
197
|
+
Use: "list",
|
|
198
|
+
Short: "List users",
|
|
199
|
+
RunE: func(cmd *cobra.Command, args []string) error {
|
|
200
|
+
return listUsers()
|
|
201
|
+
},
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
func init() {
|
|
205
|
+
rootCmd.AddCommand(userCmd)
|
|
206
|
+
userCmd.AddCommand(createUserCmd)
|
|
207
|
+
userCmd.AddCommand(listUserCmd)
|
|
208
|
+
}
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
## Completions
|
|
212
|
+
|
|
213
|
+
```go
|
|
214
|
+
var cmd = &cobra.Command{
|
|
215
|
+
Use: "set-env [environment]",
|
|
216
|
+
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
|
217
|
+
return []string{"dev", "staging", "production"}, cobra.ShellCompDirectiveNoFileComp
|
|
218
|
+
},
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// Generate completions
|
|
222
|
+
// myapp completion bash > /etc/bash_completion.d/myapp
|
|
223
|
+
// myapp completion zsh > "${fpath[1]}/_myapp"
|
|
224
|
+
```
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Go Core
|
|
3
|
+
description: Go language fundamentals, concurrency, error handling, and project patterns.
|
|
4
|
+
metadata:
|
|
5
|
+
labels: [golang, core, language]
|
|
6
|
+
triggers:
|
|
7
|
+
files: ['go.mod', '**/*.go']
|
|
8
|
+
keywords: [func, package, import, goroutine, chan]
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Go Core Standards
|
|
12
|
+
|
|
13
|
+
## Goroutines & Channels
|
|
14
|
+
|
|
15
|
+
```go
|
|
16
|
+
// Spawn goroutine
|
|
17
|
+
go func() {
|
|
18
|
+
result := process(data)
|
|
19
|
+
resultChan <- result
|
|
20
|
+
}()
|
|
21
|
+
|
|
22
|
+
// Unbuffered channel (synchronous)
|
|
23
|
+
ch := make(chan int)
|
|
24
|
+
|
|
25
|
+
// Buffered channel
|
|
26
|
+
ch := make(chan int, 100)
|
|
27
|
+
|
|
28
|
+
// Send and receive
|
|
29
|
+
ch <- value // Send
|
|
30
|
+
value := <-ch // Receive
|
|
31
|
+
|
|
32
|
+
// Select for multiplexing
|
|
33
|
+
select {
|
|
34
|
+
case msg := <-msgChan:
|
|
35
|
+
handle(msg)
|
|
36
|
+
case <-time.After(5 * time.Second):
|
|
37
|
+
return errors.New("timeout")
|
|
38
|
+
case <-ctx.Done():
|
|
39
|
+
return ctx.Err()
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
**Patterns**:
|
|
44
|
+
- Worker pools with buffered channels
|
|
45
|
+
- Fan-out/fan-in for parallel processing
|
|
46
|
+
- Done channel for cancellation
|
|
47
|
+
|
|
48
|
+
## Error Handling
|
|
49
|
+
|
|
50
|
+
```go
|
|
51
|
+
// Return errors, don't panic
|
|
52
|
+
func fetchUser(id int) (*User, error) {
|
|
53
|
+
user, err := db.FindUser(id)
|
|
54
|
+
if err != nil {
|
|
55
|
+
return nil, fmt.Errorf("fetch user %d: %w", id, err)
|
|
56
|
+
}
|
|
57
|
+
return user, nil
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Error wrapping (Go 1.13+)
|
|
61
|
+
if errors.Is(err, sql.ErrNoRows) {
|
|
62
|
+
return nil, ErrNotFound
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Type assertion for custom errors
|
|
66
|
+
var apiErr *APIError
|
|
67
|
+
if errors.As(err, &apiErr) {
|
|
68
|
+
log.Printf("API error: %d", apiErr.Code)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Sentinel errors
|
|
72
|
+
var ErrNotFound = errors.New("not found")
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
**Rules**:
|
|
76
|
+
- Always check errors immediately
|
|
77
|
+
- Wrap with context: `fmt.Errorf("operation: %w", err)`
|
|
78
|
+
- Use `errors.Is` and `errors.As` for comparison
|
|
79
|
+
- **Never**: `panic` for recoverable errors
|
|
80
|
+
|
|
81
|
+
## Interfaces
|
|
82
|
+
|
|
83
|
+
```go
|
|
84
|
+
// Small interfaces
|
|
85
|
+
type Reader interface {
|
|
86
|
+
Read(p []byte) (n int, err error)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
type Writer interface {
|
|
90
|
+
Write(p []byte) (n int, err error)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Composition
|
|
94
|
+
type ReadWriter interface {
|
|
95
|
+
Reader
|
|
96
|
+
Writer
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Accept interfaces, return structs
|
|
100
|
+
func ProcessData(r Reader) (*Result, error) {
|
|
101
|
+
data, err := io.ReadAll(r)
|
|
102
|
+
// ...
|
|
103
|
+
return &Result{}, nil
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
**Best Practices**:
|
|
108
|
+
- Define interfaces where used, not where implemented
|
|
109
|
+
- Keep interfaces small (1-3 methods)
|
|
110
|
+
- Use `interface{}` sparingly; prefer generics (Go 1.18+)
|
|
111
|
+
|
|
112
|
+
## Context
|
|
113
|
+
|
|
114
|
+
```go
|
|
115
|
+
// Pass context as first parameter
|
|
116
|
+
func fetchData(ctx context.Context, id int) (*Data, error) {
|
|
117
|
+
// Respect cancellation
|
|
118
|
+
select {
|
|
119
|
+
case <-ctx.Done():
|
|
120
|
+
return nil, ctx.Err()
|
|
121
|
+
default:
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Use context with HTTP requests
|
|
125
|
+
req, _ := http.NewRequestWithContext(ctx, "GET", url, nil)
|
|
126
|
+
return client.Do(req)
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// Add timeout
|
|
130
|
+
ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
|
|
131
|
+
defer cancel()
|
|
132
|
+
|
|
133
|
+
// Add values (use sparingly)
|
|
134
|
+
ctx = context.WithValue(ctx, requestIDKey, reqID)
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
**Rules**:
|
|
138
|
+
- Never store context in structs
|
|
139
|
+
- Always call cancel function (use defer)
|
|
140
|
+
- Use for cancellation, deadlines, request-scoped values only
|
|
141
|
+
|
|
142
|
+
## Project Structure
|
|
143
|
+
|
|
144
|
+
```
|
|
145
|
+
project/
|
|
146
|
+
├── cmd/
|
|
147
|
+
│ └── myapp/
|
|
148
|
+
│ └── main.go # Entry point
|
|
149
|
+
├── internal/ # Private packages
|
|
150
|
+
│ ├── handler/
|
|
151
|
+
│ ├── service/
|
|
152
|
+
│ └── repository/
|
|
153
|
+
├── pkg/ # Public packages
|
|
154
|
+
├── api/ # API definitions (proto, OpenAPI)
|
|
155
|
+
├── configs/
|
|
156
|
+
├── go.mod
|
|
157
|
+
└── go.sum
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
**Conventions**:
|
|
161
|
+
- `internal/` prevents external imports
|
|
162
|
+
- `cmd/` for multiple entry points
|
|
163
|
+
- Flat structure for small projects
|
|
164
|
+
|
|
165
|
+
## Testing
|
|
166
|
+
|
|
167
|
+
```go
|
|
168
|
+
// Table-driven tests
|
|
169
|
+
func TestAdd(t *testing.T) {
|
|
170
|
+
tests := []struct {
|
|
171
|
+
name string
|
|
172
|
+
a, b int
|
|
173
|
+
expected int
|
|
174
|
+
}{
|
|
175
|
+
{"positive", 1, 2, 3},
|
|
176
|
+
{"negative", -1, -1, -2},
|
|
177
|
+
{"zero", 0, 0, 0},
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
for _, tt := range tests {
|
|
181
|
+
t.Run(tt.name, func(t *testing.T) {
|
|
182
|
+
result := Add(tt.a, tt.b)
|
|
183
|
+
if result != tt.expected {
|
|
184
|
+
t.Errorf("Add(%d, %d) = %d; want %d", tt.a, tt.b, result, tt.expected)
|
|
185
|
+
}
|
|
186
|
+
})
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// Parallel tests
|
|
191
|
+
func TestParallel(t *testing.T) {
|
|
192
|
+
t.Parallel()
|
|
193
|
+
// ...
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// Benchmarks
|
|
197
|
+
func BenchmarkProcess(b *testing.B) {
|
|
198
|
+
for i := 0; i < b.N; i++ {
|
|
199
|
+
Process(data)
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
## Performance
|
|
205
|
+
|
|
206
|
+
1. **Preallocate slices**: `make([]T, 0, expectedLen)`
|
|
207
|
+
2. **Avoid allocations**: Reuse buffers, use `sync.Pool`
|
|
208
|
+
3. **Profile first**: `go tool pprof` before optimizing
|
|
209
|
+
4. **Escape analysis**: `go build -gcflags='-m'` to check heap escapes
|
|
210
|
+
5. **String building**: Use `strings.Builder` not `+` concatenation
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Go Core References
|
|
2
|
+
|
|
3
|
+
## References
|
|
4
|
+
|
|
5
|
+
- [**Error Handling**](error-handling.md) - Error wrapping, custom errors, sentinel errors
|
|
6
|
+
- [**Concurrency Patterns**](concurrency-patterns.md) - Goroutines, channels, sync primitives
|
|
7
|
+
|
|
8
|
+
## Quick Checks
|
|
9
|
+
|
|
10
|
+
- [ ] Always handle errors explicitly
|
|
11
|
+
- [ ] Use `fmt.Errorf` with `%w` for wrapping
|
|
12
|
+
- [ ] Context for cancellation and timeouts
|
|
13
|
+
- [ ] Prefer channels for communication, mutexes for state
|
|
14
|
+
- [ ] Use `defer` for cleanup
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# Concurrency Patterns
|
|
2
|
+
|
|
3
|
+
## Goroutines and Channels
|
|
4
|
+
|
|
5
|
+
```go
|
|
6
|
+
// Worker pool
|
|
7
|
+
func workerPool(jobs <-chan Job, results chan<- Result, workers int) {
|
|
8
|
+
var wg sync.WaitGroup
|
|
9
|
+
for i := 0; i < workers; i++ {
|
|
10
|
+
wg.Add(1)
|
|
11
|
+
go func() {
|
|
12
|
+
defer wg.Done()
|
|
13
|
+
for job := range jobs {
|
|
14
|
+
results <- process(job)
|
|
15
|
+
}
|
|
16
|
+
}()
|
|
17
|
+
}
|
|
18
|
+
wg.Wait()
|
|
19
|
+
close(results)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Fan-out, fan-in
|
|
23
|
+
func fanOut(input <-chan int, workers int) []<-chan int {
|
|
24
|
+
channels := make([]<-chan int, workers)
|
|
25
|
+
for i := 0; i < workers; i++ {
|
|
26
|
+
channels[i] = worker(input)
|
|
27
|
+
}
|
|
28
|
+
return channels
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
func fanIn(channels ...<-chan int) <-chan int {
|
|
32
|
+
out := make(chan int)
|
|
33
|
+
var wg sync.WaitGroup
|
|
34
|
+
for _, ch := range channels {
|
|
35
|
+
wg.Add(1)
|
|
36
|
+
go func(c <-chan int) {
|
|
37
|
+
defer wg.Done()
|
|
38
|
+
for v := range c {
|
|
39
|
+
out <- v
|
|
40
|
+
}
|
|
41
|
+
}(ch)
|
|
42
|
+
}
|
|
43
|
+
go func() {
|
|
44
|
+
wg.Wait()
|
|
45
|
+
close(out)
|
|
46
|
+
}()
|
|
47
|
+
return out
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Context for Cancellation
|
|
52
|
+
|
|
53
|
+
```go
|
|
54
|
+
func processWithTimeout(ctx context.Context) error {
|
|
55
|
+
ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
|
|
56
|
+
defer cancel()
|
|
57
|
+
|
|
58
|
+
select {
|
|
59
|
+
case result := <-doWork(ctx):
|
|
60
|
+
return handleResult(result)
|
|
61
|
+
case <-ctx.Done():
|
|
62
|
+
return ctx.Err()
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Propagate context
|
|
67
|
+
func handler(w http.ResponseWriter, r *http.Request) {
|
|
68
|
+
ctx := r.Context()
|
|
69
|
+
result, err := service.Process(ctx) // Pass context down
|
|
70
|
+
// ...
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Sync Primitives
|
|
75
|
+
|
|
76
|
+
```go
|
|
77
|
+
// Mutex for shared state
|
|
78
|
+
type Counter struct {
|
|
79
|
+
mu sync.Mutex
|
|
80
|
+
value int
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
func (c *Counter) Increment() {
|
|
84
|
+
c.mu.Lock()
|
|
85
|
+
defer c.mu.Unlock()
|
|
86
|
+
c.value++
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// RWMutex for read-heavy workloads
|
|
90
|
+
type Cache struct {
|
|
91
|
+
mu sync.RWMutex
|
|
92
|
+
data map[string]string
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
func (c *Cache) Get(key string) (string, bool) {
|
|
96
|
+
c.mu.RLock()
|
|
97
|
+
defer c.mu.RUnlock()
|
|
98
|
+
v, ok := c.data[key]
|
|
99
|
+
return v, ok
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Once for initialization
|
|
103
|
+
var (
|
|
104
|
+
instance *Config
|
|
105
|
+
once sync.Once
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
func GetConfig() *Config {
|
|
109
|
+
once.Do(func() {
|
|
110
|
+
instance = loadConfig()
|
|
111
|
+
})
|
|
112
|
+
return instance
|
|
113
|
+
}
|
|
114
|
+
```
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# Error Handling Patterns
|
|
2
|
+
|
|
3
|
+
## Error Wrapping
|
|
4
|
+
|
|
5
|
+
```go
|
|
6
|
+
import (
|
|
7
|
+
"errors"
|
|
8
|
+
"fmt"
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
// Wrap errors with context
|
|
12
|
+
func processUser(id string) error {
|
|
13
|
+
user, err := findUser(id)
|
|
14
|
+
if err != nil {
|
|
15
|
+
return fmt.Errorf("processUser: finding user %s: %w", id, err)
|
|
16
|
+
}
|
|
17
|
+
return nil
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Check for specific error
|
|
21
|
+
if errors.Is(err, ErrNotFound) {
|
|
22
|
+
// handle not found
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Extract error type
|
|
26
|
+
var validationErr *ValidationError
|
|
27
|
+
if errors.As(err, &validationErr) {
|
|
28
|
+
// handle validation error
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Custom Errors
|
|
33
|
+
|
|
34
|
+
```go
|
|
35
|
+
// Sentinel errors
|
|
36
|
+
var (
|
|
37
|
+
ErrNotFound = errors.New("not found")
|
|
38
|
+
ErrUnauthorized = errors.New("unauthorized")
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
// Custom error type
|
|
42
|
+
type ValidationError struct {
|
|
43
|
+
Field string
|
|
44
|
+
Message string
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
func (e *ValidationError) Error() string {
|
|
48
|
+
return fmt.Sprintf("validation failed: %s - %s", e.Field, e.Message)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Usage
|
|
52
|
+
return &ValidationError{Field: "email", Message: "invalid format"}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Error Handling Best Practices
|
|
56
|
+
|
|
57
|
+
```go
|
|
58
|
+
// 1. Handle errors at the appropriate level
|
|
59
|
+
func handler(w http.ResponseWriter, r *http.Request) {
|
|
60
|
+
result, err := service.Process(r.Context())
|
|
61
|
+
if err != nil {
|
|
62
|
+
switch {
|
|
63
|
+
case errors.Is(err, ErrNotFound):
|
|
64
|
+
http.Error(w, "Not found", http.StatusNotFound)
|
|
65
|
+
case errors.Is(err, ErrUnauthorized):
|
|
66
|
+
http.Error(w, "Unauthorized", http.StatusUnauthorized)
|
|
67
|
+
default:
|
|
68
|
+
log.Printf("unexpected error: %v", err)
|
|
69
|
+
http.Error(w, "Internal error", http.StatusInternalServerError)
|
|
70
|
+
}
|
|
71
|
+
return
|
|
72
|
+
}
|
|
73
|
+
json.NewEncoder(w).Encode(result)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// 2. Don't ignore errors
|
|
77
|
+
file, err := os.Open(path)
|
|
78
|
+
if err != nil {
|
|
79
|
+
return err // Don't: _ = os.Open(path)
|
|
80
|
+
}
|
|
81
|
+
defer file.Close()
|
|
82
|
+
|
|
83
|
+
// 3. Panic only for unrecoverable errors
|
|
84
|
+
if config == nil {
|
|
85
|
+
panic("config is required") // Startup only
|
|
86
|
+
}
|
|
87
|
+
```
|