Skip to content

antfroger/go-dynamic-questionnaire

Repository files navigation

Dynamic Questionnaire

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

PkgGoDev CI Go Report Card Release

Installation

go get "github.com/antfroger/go-dynamic-questionnaire"

Basic Usage

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
        }
    }
}

Features

Unified API

Single Next() method returns everything you need:

  • Questions to display
  • Closing remarks (when completed)
  • Completion status
  • Progress tracking

Progress Tracking

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
}

Closing Remarks

Show personalized messages when questionnaire is completed:

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'

Conditional Logic

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"

Response Structure

The Next() method returns 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"`
}

Configuration Format

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?"
    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'

Examples

CLI Application

Interactive command-line questionnaire with progress display:

cd examples/cli
go run main.go tech.yaml

More details in the dedicated README.

REST API Server

Complete web service with questionnaire endpoints:

cd examples/rest-api
go run main.go

API endpoints:

  • GET /questionnaires - List available questionnaires
  • POST /questionnaires/{id} - Get questions with progress and closing remarks

More details in the dedicated README.

Advanced Features

Thread-Safe Design

The library is stateless and thread-safe by design. Each questionnaire instance can be safely used across multiple goroutines.

Expression Engine

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'

Flexible Input

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)

TODOs

  • Add loaders for different configuration formats
    • read the configuration from a JSON file
    • read the configuration from JSON bytes
    • pass pre-configured questions