fasttemplate
is a relatively simple and easy to use small template library . The author of fasttemplate
, valyala, has additionally open sourced a number of excellent libraries, such as the famous fasthttp
.
fasttemlate
only focuses on a very small area - string replacement. Its goal is to replace strings.Replace
, fmt.Sprintf
and other methods to provide a simple, easy-to-use, high-performance string replacement method.
Quick Use
Create the directory and initialize.
Install the fasttemplate library.
|
|
Write the code:
|
|
- Define the template string, using
{{
and}}
for placeholders, which can be specified when creating the template - Call
fasttemplate.New()
to create a template objectt
, passing in the start and end placeholders - Call the
t.ExecuteString()
method of the template object, passing in the parameters. The parameters have the values corresponding to each placeholder. Generate the final string
Running results:
We can customize the placeholders, the above uses {{
and }}
as start and end placeholders respectively. We can replace them with [[
and ]]
with a simple code change
Also, note that the incoming parameters are of type map[string]interface{}
, but fasttemplate
only accepts values of type []byte
, string
and TagFunc
. This is why the 18
above is enclosed in double quotes.
Another point to note is that fasttemplate.New()
returns a template object, and if the template fails to parse, it will just panic
. If you want to handle the error yourself, you can call the fasttemplate.NewTemplate()
method, which returns a template object and an error.
In fact, fasttemplate.New()
internally calls fasttemplate.NewTemplate()
, and if an error is returned, it will panic
|
|
This is actually a common practice, for example, do not want to deal with the error of the program, direct panic is sometimes an option. For example, the html.template
standard library also provides the Must()
method, which is generally used to panic when a parsing failure is encountered.
|
|
No spaces inside the middle of placeholders!!!
Shortcuts
By using fasttemplate.New()
to define a template object, we can use different parameters to do the replacement multiple times. However, sometimes we have to do a lot of one-time replacements, and defining the template object each time seems tedious. fasttemplate
also provides a one-time replacement method.
Using this approach, we need to pass in both the template string, the start placeholder, the end placeholder and the substitution parameter.
TagFunc
fasttemplate
provides a TagFunc
that adds some logic to the substitution. TagFunc
is a function
|
|
When performing the replacement, fasttemplate
calls the TagFunc
function once for each placeholder, tag being the name of the placeholder. See the following program:
|
|
This is actually the TagFunc
version of the get-started
sample program, which writes different values depending on the tag
passed in. If we look at the source code we can see that ExecuteString()
actually ends up calling ExecuteFuncString()
. The fasttemplate
provides a standard TagFunc
|
|
The standard TagFunc
implementation is also very simple, that is, the corresponding value is taken from the parameter map[string]interface{}
and processed accordingly.
If it is []byte
and string
type, directly call the write method of io.Writer
. If it is of type TagFunc
, call this method directly, passing in io.Writer
and tag
. Other types throw errors directly with panic
.
If the tag
in the template does not exist in the parameter map[string]interface{}
, there are two ways to deal with it:
- is simply ignored, which is equivalent to replacing it with the empty string “”. This is how the standard stdTagFunc handles this.
- Keep the original tag. keepUnknownTagFunc does just that.
The keepUnknownTagFunc code is as follows:
|
|
The second half is handled the same as stdTagFunc
, the first half of the function if tag
is not found. Write startTag
+ tag
+ endTag
directly as the replacement value.
The ExecuteString()
method we called earlier uses stdTagFunc
, i.e. it directly replaces the unrecognized tag
with the empty string. If you want to keep the unrecognized tag
, just call the ExecuteStringStd()
method instead. This method will retain the unrecognized tag
when it encounters it
The missing age
in the parameters results in the following run
Methods with io.Writer
arguments
The previously described methods all return a string at the end. The method names all have String: ExecuteString()/ExecuteFuncString()
in them.
We can pass a io.Writer
parameter directly and call the Write()
method of this parameter to write the result string directly. This class does not have String:Execute()/ExecuteFunc()
in the method name.
|
|
Since os.Stdout
implements the io.Writer
interface, it can be passed in directly. The result is written directly to os.Stdout. Run.
Source Code Analysis
First look at the structure and creation of the template object
|
|
After the template is created the Reset()
method is called to initialize.
|
|
The initialization does the following:
- Record start and end placeholders.
- Parse the template to separate the text and tag slices and store them in the texts and tags slices respectively. The second half of the for loop does just that.
Code detail points:
- First count the total number of placeholders, construct the text and tag slices of the corresponding size at a time, and note that a properly constructed template string text slice must be 1 larger than the tag slice. like this
| text | tag | text | ... | tag | text |
. - To avoid memory copies, use unsafeString2Bytes to let the returned byte slices point directly to the string’s internal address.
Looking at the above introduction, it seems that there are many methods. In fact the core method is just one ExecuteFunc()
. All other methods call it directly or indirectly.
|
|
The Execute()
method constructs a TagFunc
to call ExecuteFunc()
, internally using stdTagFunc
.
The ExecuteString()
and ExecuteStringStd()
methods call the ExecuteFuncString()
method, which in turn calls the ExecuteFuncStringWithErr()
method,
ExecuteFuncStringWithErr()
method internally uses bytebufferpool.Get()
to get a bytebufferpoo.Buffer
object to call the ExecuteFunc()
method. So the core is the ExecuteFunc()
method
|
|
The whole logic is also very clear, for
loop is Write
a texts
element, to the current tag
to execute TagFunc
, index +1. Finally write the last texts
element, complete. It looks like this.
|
|
Summary
You can use fasttemplate
to accomplish the tasks of strings.Replace
and fmt.Sprintf
, and fasttemplate
is more flexible. The code is clear and easy to understand, worth a look.
Regarding the naming, the Execute()
method uses stdTagFunc
inside and the ExecuteStd()
method uses the keepUnknownTagFunc
method inside. I wonder if it would be better to rename stdTagFunc
to defaultTagFunc
?
Reference https://darjun.github.io/2021/05/24/godailylib/fasttemplate/