You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: runner.go
    path of file: ./repos/envconsul
    
    the code of the file until where you have to start completion: // Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"html/template"
	"io"
	"os"
	"path/filepath"
	"reflect"
	"regexp"
	"strconv"
	"strings"
	"sync"
	"time"

	"github.com/hashicorp/consul-template/child"
	"github.com/hashicorp/consul-template/config"
	dep "github.com/hashicorp/consul-template/dependency"
	"github.com/hashicorp/consul-template/watch"
	"github.com/pkg/errors"
)

// InvalidRegexp is a regexp for invalid characters in keys
var InvalidRegexp = regexp.MustCompile(`[^a-zA-Z0-9_]`)

// Runner executes a given child process with configuration
type Runner struct {
	// ErrCh and DoneCh are channels where errors and finish notifications occur.
	ErrCh  chan error
	DoneCh chan struct{}

	// ExitCh is a channel for parent processes to read exit status values from
	// the child processes.
	ExitCh chan int
    
func NewRunner(config *Config, once bool) (*Runner, error) {
	namedLogger("runner").Info("creating new runner", "once:", once)

	runner := &Runner{
		config:           config,
		once:             once,
		data:             make(map[string]interface{}),
		configPrefixMap:  make(map[string]*PrefixConfig),
		configServiceMap: make(map[string]*ServiceConfig),
		inStream:         os.Stdin,
		outStream:        os.Stdout,
		errStream:        os.Stderr,
		ErrCh:            make(chan error),
		DoneCh:           make(chan struct{}),
		ExitCh:           make(chan int, 1),
	}

	// Create the clientset
	clients, err := newClientSet(config)
	if err != nil {
		return nil, fmt.Errorf("runner: %w", err)
	}

	// needs to be run early to do initial token handling
	runner.vaultTokenWatcher, err = watch.VaultTokenWatcher(
		clients, config.Vault, runner.DoneCh)
	if err != nil {
		return nil, err
	}

	if err := runner.init(clients); err != nil {
		return nil, err
	}

	return runner, nil
}