-
Notifications
You must be signed in to change notification settings - Fork 547
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #116 from qiniu/develop
Release v2.9.20
- Loading branch information
Showing
36 changed files
with
1,661 additions
and
311 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,7 @@ | |
*.o | ||
*.a | ||
*.so | ||
.DS_Store | ||
|
||
# Folders | ||
_obj | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,209 @@ | ||
Embedded qlang (eql) | ||
======== | ||
|
||
eql 全称 embedded qlang,是类似 erubis/erb 的东西。结合 go generate 可很方便地让 Go 支持模板(不是 html template,是指语言特性中的泛型)。 | ||
|
||
## eql 程序 | ||
|
||
命令行: | ||
|
||
``` | ||
eql <template_file> [-o <output_file>] [--key1=val1 --key2=val2 ...] | ||
eql <template_dir> [-o <output_dir>] [--key1=val1 --key2=val2 ...] | ||
``` | ||
|
||
其中 | ||
|
||
* `<template_file>`: 要解析的 eql 文件,也就是模板文件。 | ||
* `<template_dir>`: 要解析的 template package,也就是整个目录是一个模板。 | ||
* `<output_file>`: 要生成的渲染后的文件。如果没有指定则为 stdout。 | ||
* `<output_dir>`: 要生成的渲染后的目标目录。如果没有指定则为对 `<template_dir>` 进行渲染后的值。 | ||
* `--key1=val1 --key2=val2 ...`: 渲染涉及到的模板变量的值。 | ||
|
||
## 样例 | ||
|
||
### 单文件模板 | ||
|
||
* [example.eql](example.eql): 展示 eql 语法的样例,下文将详细介绍。 | ||
|
||
### 目录模板 | ||
|
||
* [$set.v1](example/$set.v1): 以集合类为例展示如何构建一个 template package。 | ||
|
||
|
||
## 语法 | ||
|
||
### 插入 qlang 代码 | ||
|
||
``` | ||
<% | ||
// 在此插入 qlang 代码 | ||
%> | ||
``` | ||
|
||
### 输出 qlang 表达式 | ||
|
||
``` | ||
<%= qlang_expr %> | ||
``` | ||
|
||
你可以理解为这只是插入 qlang 代码的一种简写手法。它等价于: | ||
|
||
``` | ||
<% print(qlang_expr) %> | ||
``` | ||
|
||
### 输出一个变量 | ||
|
||
``` | ||
$var | ||
``` | ||
|
||
你可以理解为这只是插入 qlang 代码的一种简写手法。它等价于: | ||
|
||
``` | ||
<% print(var) %> | ||
``` | ||
|
||
特别地,我们用 `$$` 表示普通字符 `$`。也就是说: | ||
|
||
``` | ||
$$ | ||
``` | ||
|
||
等价于: | ||
|
||
``` | ||
<% print('$') %> | ||
``` | ||
|
||
## 用 eql 实现 Go 对泛型的支持 | ||
|
||
我们举例说明。假设我们现在实现了一个 Go 的模板类,文件名为 `example.eql`,内容如下: | ||
|
||
```go | ||
package eql_test | ||
|
||
import ( | ||
<%= eql.imports(imports) %> | ||
"encoding/binary" | ||
) | ||
|
||
// ----------------------------------------------------------------------------- | ||
|
||
type $module string | ||
|
||
func (p $module) write(out $Writer, b []byte) { | ||
|
||
_, err := out.Write(b) | ||
if err != nil { | ||
panic(err) | ||
} | ||
} | ||
|
||
<% if Writer == "*bytes.Buffer" { %> | ||
func (p $module) flush(out $Writer) { | ||
} | ||
<% } else { %> | ||
func (p $module) flush(out $Writer) { | ||
|
||
err := out.Flush() | ||
if err != nil { | ||
panic(err) | ||
} | ||
} | ||
<% } %> | ||
|
||
// ----------------------------------------------------------------------------- | ||
``` | ||
|
||
这个模板里面,有 3 个模板变量: | ||
|
||
* `imports`: 需要额外引入的 package 列表,用 `,` 分隔。 | ||
* `module`: 模板类的类名。 | ||
* `Writer`: 模板类的用到的参数类型。 | ||
|
||
有了这个模板,我们就可以用如下命令生成具体的类: | ||
|
||
``` | ||
eql example.eql -o example_bytes.go --imports=bytes --module=modbytes --Writer="*bytes.Buffer" | ||
``` | ||
|
||
这会生成 example_bytes.go 文件,内容如下: | ||
|
||
```go | ||
package eql_test | ||
|
||
import ( | ||
"bytes" | ||
"encoding/binary" | ||
) | ||
|
||
// ----------------------------------------------------------------------------- | ||
|
||
type modbytes string | ||
|
||
func (p modbytes) write(out *bytes.Buffer, b []byte) { | ||
|
||
_, err := out.Write(b) | ||
if err != nil { | ||
panic(err) | ||
} | ||
} | ||
|
||
func (p modbytes) flush(out *bytes.Buffer) { | ||
} | ||
|
||
// ----------------------------------------------------------------------------- | ||
``` | ||
|
||
再试试换一个 Writer: | ||
|
||
``` | ||
eql example.eql -o example_bufio.go --imports=bufio --module=modbufio --Writer="*bufio.Writer" | ||
``` | ||
|
||
我们得到 example_bufio.go,内容如下: | ||
|
||
```go | ||
package eql_test | ||
|
||
import ( | ||
"bufio" | ||
"encoding/binary" | ||
) | ||
|
||
// ----------------------------------------------------------------------------- | ||
|
||
type modbufio string | ||
|
||
func (p modbufio) write(out *bufio.Writer, b []byte) { | ||
|
||
_, err := out.Write(b) | ||
if err != nil { | ||
panic(err) | ||
} | ||
} | ||
|
||
func (p modbufio) flush(out *bufio.Writer) { | ||
|
||
err := out.Flush() | ||
if err != nil { | ||
panic(err) | ||
} | ||
} | ||
|
||
// ----------------------------------------------------------------------------- | ||
``` | ||
|
||
### 结合 go generate | ||
|
||
结合 go generate 工具,我们就可以很好地支持 Go 泛型了。 | ||
|
||
例如假设我们在 foo.go 里面引用了 Writer = `*bufio.Writer` 版本的实现,则只需要在 foo.go 文件中插入以下代码: | ||
|
||
```go | ||
//go:generate eql example.eql -o example_bufio.go --imports=bufio --module=module --Writer=*bufio.Writer | ||
``` | ||
|
||
如此,你只需要在 foo.go 所在的目录执行 go generate 就可以生成 example_bufio.go 文件了。 |
Oops, something went wrong.