GoHCL does not support interpolation
I noticed this issue.
It mentioned that GoHCL only supports static values, and it would convert all string beginning with ${ to $ $${. It brings some problem when using interpolation.
https://github.com/hashicorp/hcl/blob/7208bce57fadb72db3a328ebc9aa86489cd06fce/hclwrite/generate.go#L367-L372
Could it support something like \$ to deal with interpolation string? I think it would not corrupt compatibility.
In fact, I am a little confused. If we know that it is a interpolation, why should we escape it?
Hi @FLAGLORD,
I'm not sure I follow what you are referring to, since the summary of the issue talks about gohcl but the code you've linked to is in hclwrite.
However, I think what you are asking amounts to: "why can't hclwrite just assume that if I have ${ in my string then I intend it to be a template interpolation sequence?", and the answer is that if that were true then decoding and re-encoding would be asymmetrical: there's no way for expression evaluation to produce a string template because evaluating string templates into strings is part of the expression evaluation process. Conversely, after evaluation there is no longer any record of the fact that the string originated as a string template: it's just a literal string value. If that string contains ${ then that's because the original string template contained $${ -- the interpolation escape sequence -- and so it's correct for the encoder to reverse that and transform it back to $${ again.
If you want to produce HCL syntax rather than HCL values then gohcl is the wrong level of abstraction for that. The hclwrite API is the appropriate API to use if you want to produce specific syntax; that package is designed to work with the HCL syntax tree instead of with values.
Hi @apparentlymart. Thanks for your rapid and detailed reply.
I want to provide some background information: I hope to generate a HCL syntax file with some existing configuration information. But I found that hclwrite is too low-level, and thus it is flexible but a little tedious. With gohcl, I can define a struct(of course with hcl tags), initialize it and invoke gohcl.EncodeIntoBody() to convert it to hcl.Body. The hclwrite code linked above is actually invoked in the execution of gohcl.EncodeIntoBody().
The symmetry of decoding and re-encoding you mentioned is really a key point, and I roughly got it. But I'm still a little confused. In your example, original string template contained $${ and decoder decodes it to ${, so it is reasonable for encoder to transform it back to ${{. But what if original string template contained ${? Would it be replaced by interpolation in the decodinng process? Is there something like parse instead of eval?
For ASCII escape characters like \t and \n, encoder and decoder really works perfectly. But for interpolation templates, golang actually does not support interpolation syntax like ${ and %{ as they are HCL-specific. Even if decoder decodes ${ to ${ and ${{ to ${{, developers wouldn't gain anything but also wouldn't lose anything, but it provides a way for developers to produce interpolation template.