Improved flow
This commit is contained in:
409
docs/guides/go-workflow.md
Normal file
409
docs/guides/go-workflow.md
Normal file
@@ -0,0 +1,409 @@
|
||||
# Go Development Workflow
|
||||
|
||||
This guide covers Go development in Neovim with gopls, testing, and debugging.
|
||||
|
||||
## Overview
|
||||
|
||||
Your config includes:
|
||||
- **LSP**: gopls (via LazyVim go extra)
|
||||
- **Linting**: golangci-lint
|
||||
- **Testing**: go test via neotest
|
||||
- **Debugging**: delve via DAP
|
||||
- **Formatting**: gofmt/goimports
|
||||
|
||||
## Getting Started
|
||||
|
||||
### Project Setup
|
||||
|
||||
1. Ensure Go is installed and `GOPATH` is set
|
||||
2. Open your Go project:
|
||||
```bash
|
||||
nvim /path/to/project
|
||||
```
|
||||
|
||||
3. gopls will auto-start when you open a `.go` file
|
||||
|
||||
### Module Initialization
|
||||
|
||||
If starting fresh:
|
||||
```bash
|
||||
go mod init myproject
|
||||
```
|
||||
|
||||
## LSP Features
|
||||
|
||||
### Navigation
|
||||
|
||||
| Key | Action |
|
||||
|-----|--------|
|
||||
| `gd` | Go to definition |
|
||||
| `gr` | Go to references |
|
||||
| `gI` | Go to implementation |
|
||||
| `gy` | Go to type definition |
|
||||
| `K` | Hover documentation |
|
||||
|
||||
### Code Actions
|
||||
|
||||
| Key | Action |
|
||||
|-----|--------|
|
||||
| `<leader>ca` | Code actions |
|
||||
| `<leader>cr` | Rename symbol |
|
||||
| `<leader>cf` | Format (gofmt) |
|
||||
|
||||
### Go-Specific Actions
|
||||
|
||||
Press `<leader>ca` for:
|
||||
- Add import
|
||||
- Organize imports
|
||||
- Extract function
|
||||
- Extract variable
|
||||
- Generate interface stubs
|
||||
- Add struct tags
|
||||
- Fill struct
|
||||
|
||||
### Diagnostics
|
||||
|
||||
| Key | Action |
|
||||
|-----|--------|
|
||||
| `<leader>cd` | Line diagnostics |
|
||||
| `]d` / `[d` | Next/prev diagnostic |
|
||||
| `<leader>xx` | Toggle trouble |
|
||||
|
||||
## Testing
|
||||
|
||||
### Running Tests
|
||||
|
||||
| Key | Action |
|
||||
|-----|--------|
|
||||
| `<leader>tt` | Run test at cursor |
|
||||
| `<leader>tf` | Run file tests |
|
||||
| `<leader>ta` | Run all tests |
|
||||
| `<leader>tl` | Re-run last test |
|
||||
|
||||
### Test File Convention
|
||||
|
||||
Go tests live in `*_test.go` files:
|
||||
|
||||
```go
|
||||
// math_test.go
|
||||
package math
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestAdd(t *testing.T) {
|
||||
result := Add(2, 3)
|
||||
if result != 5 {
|
||||
t.Errorf("expected 5, got %d", result)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Test Output
|
||||
|
||||
```
|
||||
<leader>ts Toggle test summary
|
||||
<leader>to Show test output
|
||||
<leader>tO Toggle output panel
|
||||
]t / [t Jump to failed tests
|
||||
```
|
||||
|
||||
### Table-Driven Tests
|
||||
|
||||
Common Go pattern - cursor on any test case runs it:
|
||||
|
||||
```go
|
||||
func TestAdd(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
a, b int
|
||||
expected int
|
||||
}{
|
||||
{"positive", 2, 3, 5},
|
||||
{"negative", -1, -1, -2},
|
||||
{"zero", 0, 0, 0},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
// <leader>tt here runs this specific case
|
||||
if got := Add(tt.a, tt.b); got != tt.expected {
|
||||
t.Errorf("got %d, want %d", got, tt.expected)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Debugging Tests
|
||||
|
||||
```
|
||||
<leader>td Debug test at cursor
|
||||
```
|
||||
|
||||
## Debugging with Delve
|
||||
|
||||
### Prerequisites
|
||||
|
||||
Install delve:
|
||||
```bash
|
||||
go install github.com/go-delve/delve/cmd/dlv@latest
|
||||
```
|
||||
|
||||
### Setting Breakpoints
|
||||
|
||||
| Key | Action |
|
||||
|-----|--------|
|
||||
| `<leader>db` | Toggle breakpoint |
|
||||
| `<leader>dB` | Conditional breakpoint |
|
||||
|
||||
### Running Debugger
|
||||
|
||||
| Key | Action |
|
||||
|-----|--------|
|
||||
| `<leader>dc` | Continue/Start |
|
||||
| `<leader>di` | Step into |
|
||||
| `<leader>do` | Step over |
|
||||
| `<leader>dO` | Step out |
|
||||
| `<leader>dt` | Terminate |
|
||||
|
||||
### DAP UI
|
||||
|
||||
```
|
||||
<leader>du Toggle DAP UI
|
||||
<leader>de Evaluate expression
|
||||
```
|
||||
|
||||
### launch.json
|
||||
|
||||
For custom debug configs, create `.vscode/launch.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Debug Package",
|
||||
"type": "go",
|
||||
"request": "launch",
|
||||
"mode": "debug",
|
||||
"program": "${fileDirname}"
|
||||
},
|
||||
{
|
||||
"name": "Debug Main",
|
||||
"type": "go",
|
||||
"request": "launch",
|
||||
"mode": "debug",
|
||||
"program": "${workspaceFolder}/cmd/myapp"
|
||||
},
|
||||
{
|
||||
"name": "Attach to Process",
|
||||
"type": "go",
|
||||
"request": "attach",
|
||||
"mode": "local",
|
||||
"processId": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Code Quality
|
||||
|
||||
### Formatting
|
||||
|
||||
Go code is auto-formatted on save. Manual format:
|
||||
```
|
||||
<leader>cf Format with gofmt
|
||||
```
|
||||
|
||||
### Imports
|
||||
|
||||
goimports manages imports automatically:
|
||||
- Adds missing imports on save
|
||||
- Removes unused imports
|
||||
- Sorts imports
|
||||
|
||||
### Linting
|
||||
|
||||
golangci-lint runs automatically. View issues:
|
||||
```
|
||||
<leader>xx Toggle trouble (all diagnostics)
|
||||
```
|
||||
|
||||
### Struct Tags
|
||||
|
||||
Generate/modify struct tags via code actions:
|
||||
|
||||
```go
|
||||
type User struct {
|
||||
Name string // <leader>ca → "Add json tag"
|
||||
Email string
|
||||
}
|
||||
```
|
||||
|
||||
Result:
|
||||
```go
|
||||
type User struct {
|
||||
Name string `json:"name"`
|
||||
Email string `json:"email"`
|
||||
}
|
||||
```
|
||||
|
||||
## AI Assistance
|
||||
|
||||
| Key | Action |
|
||||
|-----|--------|
|
||||
| `<leader>ka` | Ask opencode |
|
||||
| `<leader>ke` | Explain code |
|
||||
| `<leader>kR` | Refactor selection |
|
||||
| `<leader>kt` | Generate tests |
|
||||
| `<leader>kd` | Generate comments |
|
||||
|
||||
### Generate Tests
|
||||
|
||||
1. Select function in visual mode
|
||||
2. `<leader>kt`
|
||||
3. Review generated table-driven tests
|
||||
|
||||
## Common Workflows
|
||||
|
||||
### Starting New Feature
|
||||
|
||||
1. Create/open `.go` file
|
||||
2. `<leader>H` - Mark with harpoon
|
||||
3. Write code, LSP handles imports
|
||||
4. `<leader>tt` - Test as you go
|
||||
|
||||
### Implementing Interface
|
||||
|
||||
1. Write struct
|
||||
2. `<leader>ca` → "Generate interface stubs"
|
||||
3. Select interface to implement
|
||||
4. Fill in method bodies
|
||||
|
||||
### Debugging
|
||||
|
||||
1. `<leader>db` - Set breakpoint
|
||||
2. `<leader>dc` - Start debugger
|
||||
3. Use step commands to navigate
|
||||
4. `<leader>de` - Evaluate expressions
|
||||
5. `<leader>dt` - Terminate when done
|
||||
|
||||
### Error Handling
|
||||
|
||||
Common Go pattern - AI can help:
|
||||
|
||||
1. Write function that returns error
|
||||
2. `<leader>ka` - "Add proper error handling"
|
||||
3. Or use snippet (if configured):
|
||||
```go
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
```
|
||||
|
||||
## Project Structure
|
||||
|
||||
### Standard Layout
|
||||
|
||||
```
|
||||
myproject/
|
||||
├── cmd/
|
||||
│ └── myapp/
|
||||
│ └── main.go
|
||||
├── internal/
|
||||
│ └── pkg/
|
||||
├── pkg/
|
||||
│ └── public/
|
||||
├── go.mod
|
||||
└── go.sum
|
||||
```
|
||||
|
||||
### go.mod
|
||||
|
||||
```go
|
||||
module github.com/user/myproject
|
||||
|
||||
go 1.21
|
||||
|
||||
require (
|
||||
github.com/some/dependency v1.0.0
|
||||
)
|
||||
```
|
||||
|
||||
## Tips
|
||||
|
||||
### Quick Run
|
||||
|
||||
```
|
||||
:!go run . Run current package
|
||||
:!go run main.go Run specific file
|
||||
```
|
||||
|
||||
Or use executor:
|
||||
```
|
||||
<leader>Brs Set command: go run .
|
||||
<leader>Brr Run it
|
||||
```
|
||||
|
||||
### Build
|
||||
|
||||
```
|
||||
:!go build . Build current package
|
||||
```
|
||||
|
||||
### Generate
|
||||
|
||||
```
|
||||
:!go generate ./... Run go generate
|
||||
```
|
||||
|
||||
### Module Commands
|
||||
|
||||
```
|
||||
:!go mod tidy Clean up go.mod
|
||||
:!go mod download Download dependencies
|
||||
```
|
||||
|
||||
### Documentation
|
||||
|
||||
- `K` on any symbol shows docs
|
||||
- Works with standard library
|
||||
- Shows function signatures
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### gopls Not Starting
|
||||
|
||||
1. `:LspInfo` - Check status
|
||||
2. Verify gopls is installed:
|
||||
```bash
|
||||
go install golang.org/x/tools/gopls@latest
|
||||
```
|
||||
3. Check `go.mod` exists in project root
|
||||
|
||||
### Imports Not Working
|
||||
|
||||
1. Check gopls is running: `:LspInfo`
|
||||
2. Verify `goimports` is installed:
|
||||
```bash
|
||||
go install golang.org/x/tools/cmd/goimports@latest
|
||||
```
|
||||
|
||||
### Debugger Issues
|
||||
|
||||
1. Verify delve is installed:
|
||||
```bash
|
||||
go install github.com/go-delve/delve/cmd/dlv@latest
|
||||
```
|
||||
2. Check `:DapShowLog` for errors
|
||||
3. Ensure code is compiled (not just source)
|
||||
|
||||
### Slow LSP
|
||||
|
||||
1. Check for large generated files
|
||||
2. Add to `.gopls.json`:
|
||||
```json
|
||||
{
|
||||
"build.directoryFilters": ["-vendor", "-node_modules"]
|
||||
}
|
||||
```
|
||||
Reference in New Issue
Block a user