stringgographqlformatting

How to pass a variable in a string block?


In the following example code, I am trying to use graphql query and I have to pass the value of a string that I get from the command-line argument in the query:

package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "io/ioutil"
    "net/http"
    "time"
    "os"
)

func main() {
    input := os.Args[1]
    jsonData := map[string]string{
        "query": `
           mutation manager($input: managerinput!) {
              manager(input: $input) {
                 name {
                  
                  }
               error {
                 ...SystemError
                }
               }
            }

        `,
    }
    jsonValue, _ := json.Marshal(jsonData)
    request, err := http.NewRequest("POST", "https://<GRAPHQL_API_HERE>", bytes.NewBuffer(jsonValue))
    client := &http.Client{Timeout: time.Second * 10}
    response, err := client.Do(request)
    defer response.Body.Close()
    if err != nil {
        fmt.Printf("The HTTP request failed with error %s\n", err)
    }
    data, _ := ioutil.ReadAll(response.Body)
    fmt.Println(string(data))
}

How do I pass the value of input in the query block? the $input is not working but I am new and I am unable to find a way to pass the value of a variable inside a multi-line string block "query", that starts and ends with `.


Solution

  • Use text/template (Go playground):

    package main
    
    import (
        "encoding/json"
        "fmt"
        "strings"
        "text/template"
    )
    
    type Param struct {
        Input string
    }
    
    func main() {
        param := Param{Input: "some string"}
    
        tmpl, err := template.New("query").Parse(`
               mutation manager({{js .Input}}: managerinput!) {
                  manager(input: {{js .Input}}) {
                     name {
                      
                      }
                   error {
                     ...SystemError
                    }
                   }
                }
            `)
        if err != nil {
            panic(err)
        }
    
        var s strings.Builder
        err = tmpl.Execute(&s, param)
        if err != nil {
            panic(err)
        }
        query := s.String()
    
        fmt.Println(query)
    
        jsonData := map[string]string{
            "query": query,
        }
    
        jsonValue, err := json.MarshalIndent(jsonData, "*", " ")
        if err != nil {
            panic(err)
        }
    
        fmt.Println(string(jsonValue))
    }
    

    Refer to the documentation for details:

    Templates are executed by applying them to a data structure. Annotations in the template refer to elements of the data structure (typically a field of a struct or a key in a map) to control execution and derive values to be displayed.

    So, I'm using .Input here as the (exported) field of my Param structure and js as a function to escape the argument.