Go 1.23 Language Features
New Features:
- Range over integers using for i range 10 syntax and print i
- Profile-Guided Optimization PGO 2.0
- Improved generics with better type inference
Generics Pattern:
Create generic Map function with type parameters T and U as any. Accept slice of T and function from T to U. Create result slice of U with same length. Iterate range slice setting result elements to function applied to values. Return result.
Web Framework Fiber v3
Create app with fiber.New passing fiber.Config with ErrorHandler and Prefork true. Use recover.New, logger.New, and cors.New middleware. Create api group at api/v1 path. Define routes for listUsers, getUser with id parameter, createUser, updateUser with id, and deleteUser with id. Call app.Listen on port 3000.
Web Framework Gin
Create r with gin.Default. Use cors.Default middleware. Create api group at api/v1 path. Define GET for users calling listUsers, GET for users/:id calling getUser, POST for users calling createUser. Call r.Run on port 3000.
Request Binding Pattern:
Define CreateUserRequest struct with Name and Email fields. Add json tags and binding tags for required, min length 2, and required email validation. In createUser handler, declare req variable, call c.ShouldBindJSON with pointer. If error, call c.JSON with 400 status and error. Otherwise call c.JSON with 201 and response data.
Web Framework Echo
Create e with echo.New. Use middleware.Logger, middleware.Recover, and middleware.CORS. Create api group at api/v1 path. Define GET for users and POST for users. Call e.Logger.Fatal with e.Start on port 3000.
Web Framework Chi
Create r with chi.NewRouter. Use middleware.Logger and middleware.Recoverer. Call r.Route with api/v1 path and function. Inside, call r.Route with users path. Define Get for list, Post for create, Get with id parameter for single user. Call http.ListenAndServe on port 3000 with r.
ORM GORM 1.25
Model Definition:
Define User struct embedding gorm.Model. Add Name with uniqueIndex and not null tags, Email with uniqueIndex and not null, and Posts slice with foreignKey AuthorID tag.
Query Patterns:
Call db.Preload with Posts and function that orders by created_at desc and limits to 10, then First with user and id 1. For transactions, call db.Transaction with function taking tx pointer. Inside, create user and profile, returning any errors.
Type-Safe SQL with sqlc
Create sqlc.yaml with version 2, sql section with postgresql engine, queries and schema paths, and go generation settings for package name, output directory, and pgx v5 sql_package.
In query.sql file, add name GetUser as one returning all columns where id matches parameter. Add name CreateUser as one inserting name and email values and returning all columns.
Concurrency Patterns
Errgroup Pattern:
Create g and ctx with errgroup.WithContext. Call g.Go for fetchUsers that assigns to users variable. Call g.Go for fetchOrders that assigns to orders variable. If g.Wait returns error, return nil and error.
Worker Pool Pattern:
Define workerPool function taking jobs receive-only channel, results send-only channel, and n worker count. Create WaitGroup. Loop n times, incrementing WaitGroup and spawning goroutine that defers Done, ranges over jobs, and sends processJob result to results. Wait then close results.
Context with Timeout:
Create ctx and cancel with context.WithTimeout for 5 seconds. Defer cancel call. Call fetchData with ctx. If error is context.DeadlineExceeded, respond with timeout and StatusGatewayTimeout.
Testing Patterns
Table-Driven Tests:
Define tests slice with struct containing name string, input CreateUserInput, and wantErr bool. Add test cases for valid input and empty name. Range over tests calling t.Run with name and test function. Call service Create, check if wantErr is true and require.Error.
HTTP Testing:
Create app with fiber.New. Add GET route for users/:id calling getUser. Create request with httptest.NewRequest for GET at users/1. Call app.Test with request to get response. Assert 200 status code.
CLI Cobra with Viper
Define rootCmd as cobra.Command pointer with Use and Short fields. In init function, add PersistentFlags StringVar for cfgFile. Call viper.BindPFlag with config and lookup. Set viper.SetEnvPrefix to MYAPP and call viper.AutomaticEnv.
---