The Go Dynamic Questionnaire is a Go library that creates dynamic questionnaires.
Want to create a questionnaire for your Go project that adapts the next questions based on previous answers?
Go Dynamic Questionnaire is what you're looking for!
You can even provide recommendations or closing remarks based on the responses.
Dynamic Questionnaire requires Go >= 1.23
go get "github.com/antfroger/go-dynamic-questionnaire"
Use questionnaire.New("config.yaml")
to create and initialize the questionnaire based on your config.
import "github.com/antfroger/go-dynamic-questionnaire"
func main() {
q, err := questionnaire.New("config.yaml")
if err != nil {
// ...
}
answers := make(map[string]int)
for {
response, err := q.Next(answers)
if err != nil {
// ...
}
// When the questionnaire is completed, display closing remarks
if response.Completed {
displayClosingRemarks(response.ClosingRemarks)
break
}
// Display progress if available
if response.Progress != nil {
fmt.Printf("Progress: %d/%d questions answered\n", response.Progress.Current, response.Progress.Total)
}
// Ask the questions and get the answers from the user
for _, question := range response.Questions {
answer := getUserAnswer(question)
answers[question.Id] = answer
}
}
}
Create questionnaires using YAML:
questions:
- id: "satisfaction"
text: "How satisfied are you with our service?"
answers:
- "Very Satisfied"
- "Satisfied"
- "Neutral"
- "Dissatisfied"
- "Very Dissatisfied"
- id: "recommendation"
text: "Would you recommend us to others?"
depends_on: ["satisfaction"]
condition: 'answers["satisfaction"] in [1,2]'
answers:
- "Definitely"
- "Probably"
- "Maybe"
closing_remarks:
- id: "thank_you"
text: "Thank you for your feedback!"
- id: "follow_up"
text: "We'll reach out to address your concerns."
condition: 'answers["satisfaction"] >= 4'
Single Next()
method returns everything you need:
- Questions to display
- Closing remarks (when completed)
- Completion status
- Progress tracking
in a unified response:
type Response struct {
Questions []Question `json:"questions"`
ClosingRemarks []ClosingRemark `json:"closing_remarks,omitempty"`
Completed bool `json:"completed"`
Progress *Progress `json:"progress,omitempty"`
}
Show personalized messages when questionnaire is completed:
type ClosingRemark struct {
Id string `json:"id"` // Unique identifier for the remark
Text string `json:"text"` // The message text to display
}
Configure closing remarks in your YAML:
closing_remarks:
- id: "general"
text: "Thank you for completing the questionnaire!"
- id: "specific"
text: "Based on your answers, here's our recommendation..."
condition: 'answers["interest"] == 1'
Track user progress through the questionnaire:
type Progress struct {
Current int `json:"current"` // Questions answered
Total int `json:"total"` // Total questions in the current path
}
Dynamic question flow based on previous answers:
questions:
- id: "experience"
text: "Do you have programming experience?"
answers:
- "Yes"
- "No"
- id: "language"
text: "Which language do you prefer?"
condition: 'answers["experience"] == 1'
answers:
- "Go"
- "Python"
- "JavaScript"
Interactive command-line questionnaire with progress display:
cd examples/cli
go run main.go tech.yaml
More details in the dedicated README.
Complete web service with questionnaire endpoints:
cd examples/rest-api
go run main.go
API endpoints:
GET /questionnaires
- List available questionnairesPOST /questionnaires/{id}
- Get questions with progress and closing remarks
More details in the dedicated README.
The library is stateless and thread-safe by design. Each questionnaire instance can be safely used across multiple goroutines.
Powerful condition expressions using the expr
library:
condition: 'answers["age"] >= 18 and answers["country"] == "US"'
condition: 'answers["score"] in 1..5'
condition: 'len(answers) >= 3'
Load questionnaires from files or byte arrays:
// From file
q, err := questionnaire.New("config.yaml")
// From bytes
yamlData := []byte(`questions: ...`)
q, err := questionnaire.New(yamlData)
- Add loaders for different configuration formats
Introduce a loader interface to handle different config types. These loaders would be responsible for reading from files, parsing YAML/JSON, etc.- read the configuration from a JSON file
- read the configuration from JSON bytes
- pass pre-configured questions
- Question type system (text input, numbers, etc.)
- Question validation (required fields, formats)
- Performance optimizations for large questionnaires
- Pre-compute which questions are available
- Cache condition evaluation results
- Internationalization support
- Advanced branching logic and survey flows
- Builder pattern for easier questionnaire construction