This project is a simple To-do application built with Go. While it covers basic features like marking tasks as important, the main goal here is to showcase how to implement Dependency Inversion and Dependency Injection in Go projects. We'll explore both manual methods and popular DI libraries like Uber fx and Google wire.
This repository has four branches, each highlighting different approaches to dependency management:
without_dep_inv(default): The starting point with basic dependency injection, without dependency inversion.with_dep_inv: Introduces Dependency Inversion to address the initial shortcomings.using_fx: Implements Dependency Injection using the Uber fx library.using_wire: Utilizes Google wire for Dependency Injection.
This branch represents our initial Go project setup with basic dependency management.
-
Tight Coupling Between Repository and Service
- Why it’s bad: Makes it hard to swap out implementations or reuse components. Testing becomes a headache because dependencies are concrete and not easily mockable.
-
Tight Coupling Between CLI Commands, Service, and Zap Logger
- Why it’s bad: Besides design rigidity and testing difficulties, having direct ties to external libraries like Zap means any updates or changes can lead to costly migrations.
Without Dependency Inversion and Dependency Injection, your codebase can quickly become rigid and difficult to maintain. It hampers flexibility, modularity, and makes automated testing a nightmare.
Ready to see improvements? Check out the with_dep_inv branch to see how we tackle these issues by introducing Dependency Inversion. From there, you can explore using_fx and using_wire to see how different DI libraries can streamline your project.
- Go: Make sure you have Go installed. You can download it from golang.org.
- Docker: For running the MySQL database. You can download it from docs.docker.com/engine/install.
To run the Go Todo DI application, you'll need a MySQL database. Using Docker simplifies the setup process.
-
Pull the MySQL Docker Image
docker pull mysql:latest
-
Start the MySQL Container
Replace
your_passwordwith a secure password of your choice.docker run --name go-todo-mysql -e MYSQL_ROOT_PASSWORD=your_password -e MYSQL_DATABASE=todo_db -p 3306:3306 -d mysql:latest
-
Verify the MySQL Container is Running
docker ps | grep go-todo-mysqlYou should see an entry for
go-todo-mysqlin the list of running containers.
-
Clone the Repository
git clone https://github.com/SBTopZZZ-LG/go-dependency-injection.git
-
Navigate to the Project Directory
cd go-todo-di -
Checkout the
without_dep_invBranchgit checkout without_dep_inv
-
Install dependencies
go mod tidy
-
Create Application Configuration
Generate the
config.yamlfile with the necessary configurations:cat <<'EOF' > config.yaml logger: level: "info" development: true encoding: "json" output_paths: - "./logs/all-logs.log" error_output_paths: - "./logs/errors.log" encoder_config: line_ending: "\n" database: driver: "mysql" user: "root" password: "your_password" host: "localhost" port: 3306 name: "todo_db" params: "parseTime=true" EOF
Note: Replace your_password with the password you set for the MySQL root user.
-
Create Logs Directory
To prevent the application from crashing due to missing log directories, create the
logsfolder:mkdir logs
-
Run the Application
go run main.go
The application should now be running, and you can interact with the CLI to manage your To-dos.
Interact with the Go Todo DI application using the following commands. Each command allows you to manage your to-dos effectively through the CLI.
go run main.go <command> [{<id>|<content>|<id> <content>}]Syntax
go run main.go create_todo <message>Example
go run main.go create_todo "Write a Blog"Syntax
go run main.go list_todosRetrieve a specific to-do using its unique ID.
Syntax
go run main.go get_todo <id>Example
go run main.go get_todo 1Syntax
go run main.go update_todo <id> <new_message>Example
go run main.go update_todo 1 "Buy groceries and cook dinner"Syntax
go run main.go delete_todo <id>Example
go run main.go delete_todo 1Flag a to-do as important to prioritize it.
Syntax
go run main.go make_todo_important <id>Example
go run main.go make_todo_important 1Remove the important flag from a to-do.
Syntax
go run main.go make_todo_not_important <id>Example
go run main.go make_todo_not_important 1