Skip to content

Commit

Permalink
Merge pull request #116 from qiniu/develop
Browse files Browse the repository at this point in the history
Release v2.9.20
  • Loading branch information
xushiwei committed Jun 9, 2016
2 parents 19d9823 + 3303ab2 commit 5f6992a
Show file tree
Hide file tree
Showing 36 changed files with 1,661 additions and 311 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
*.o
*.a
*.so
.DS_Store

# Folders
_obj
Expand Down
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,9 +117,13 @@ git clone https://github.com/qiniu/text.git qiniupkg.com/text

## 社区资源

### Embedded qlang (eql)

* [eql](app/eql): 全称 [embedded qlang](app/eql),是类似 erubis/erb 的东西。结合 go generate 可很方便地让 Go 支持模板(不是 html template,是指泛型)。

### 为 Go package 导出 qlang module

* [qexport](app/qexport/README.md): 可为 Go 语言的标准库或者你自己写的 Go Package 自动导出相应的 qlang module。
* [qexport](app/qexport): 可为 Go 语言的标准库或者你自己写的 Go Package 自动导出相应的 qlang module。

### Qlang Modules

Expand Down
3 changes: 1 addition & 2 deletions README_QL.md
Original file line number Diff line number Diff line change
Expand Up @@ -680,12 +680,11 @@ func (p *Bar) GetX() int {

```go
import (
"reflect"
"qlang.io/qlang.spec.v1"
)

var Exports = map[string]interface{}{
"Bar": qlang.NewType(reflect.TypeOf((*foo.Bar)(nil)).Elem()),
"Bar": qlang.StructOf((*foo.Bar)(nil)),
}
```

Expand Down
209 changes: 209 additions & 0 deletions app/eql/README.md
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 文件了。
Loading

0 comments on commit 5f6992a

Please sign in to comment.