Go 实现泛型展开以及展开时计算

taowen 发表了文章 • 0 个评论 • 271 次浏览 • 3 天前 • 来自相关话题

实现代码: https:/... 查看全部

实现代码: https://github.com/v2pro/wombat/tree/master/fp


泛型展开


泛型展开不是简单的类型替换。在C++中有模板偏特化,以及由此发展出来一系列实现编译期计算的奇技淫巧,直到最后以constexpr变成语言的一部分。D语言的static if也是类似的,在编译期实现了D语言的一个子集。在 Go 2.0 中即便支持了泛型,要达到D语言的高度,可能还需要很长的路要走。所以目前最佳的方案还是用代码生成的方案。但是纯手写的代码生成没有办法做到很复杂的泛型代码的组合,比如一个泛型函数调用另外一个泛型函数之类的。所以 wombat 的实现目标是设计一个能够支撑大规模代码生成的机制,使得复杂的utility能够被广泛复用。这些utility可能简单的如compare,max,复杂得如json编解码。


最简单的例子


定义一个泛型的函数


var compareSimpleValue = generic.DefineFunc("CompareSimpleValue(val1 T, val2 T) int").
Param("T", "the type of value to compare").
Source(`
if val1 < val2 {
return -1
} else if val1 == val2 {
return 0
} else {
return 1
}`)

测试一个泛型的函数


func init() {
generic.DynamicCompilationEnabled = true
}

func Test_compare_int(t *testing.T) {
should := require.New(t)
f := generic.Expand(compareSimpleValue, "T", generic.Int).
(func(int, int) int)
should.Equal(-1, f(3, 4))
should.Equal(0, f(3, 3))
should.Equal(1, f(4, 3))
}

注意,在init的时候,我们开启了动态编译。这样在测试的时候,实际上是直接在执行的时候生成代码,并用plugin的方式加载的。这样测试泛型代码就能达到和反射的实现一样的高效。


使用一个泛型的函数


func init() {
generic.Declare(compareSimpleValue, "T", generic.Int)
}

func xxx() {
f := generic.Expand(compareSimpleValue, "T", generic.Int).
(func(int, int) int)
f(3, 4)
}

因为没有开启动态编译,所以调用generic.Expand会失败。需要用 go install github.com/v2pro/wombat/cmd/codegen 编译出代码生成器。然后执行


codegen -pkg path-to-your-pkg

然后会在你的包下面生成 generated.go 文件。这样运行时generic.Expand 就不会报错了。


泛型展开时计算


如果需求不仅仅是支持int,还要支持int的指针。前面实现的函数模板是无法支持的。所以我们需要能够,在泛型展开的时候进行类型判断,选择不同的实现。


var ByItself = generic.DefineFunc("CompareByItself(val1 T, val2 T) int").
Param("T", "the type of value to compare").
Generators("dispatch", dispatch).
Source(`
{{ $compare := expand (.T|dispatch) "T" .T }}
return {{$compare}}(val1, val2)`)

func dispatch(typ reflect.Type) string {
switch typ.Kind() {
case reflect.Int:
return "CompareSimpleValue"
case reflect.Ptr:
return "ComparePtr"
}
panic("unsupported type: " + typ.String())
}

其中dispatch就是一个go语言实现的函数,可以在展开模板的时候被调用,用于选择具体的实现。然后调用expand来把对应的模板再展开,然后调用。


递归展开


ComparePtr其实无法确认自己一定是调用CompareSimpleValue。因为可能还有**int,以及***int这样的情况。所以,ComparePtr在对指针进行取消引用之后,再次调用CompareByItself进行递归展开模板。


func init() {
ByItself.ImportFunc(comparePtr)
}

var comparePtr = generic.DefineFunc("ComparePtr(val1 T, val2 T) int").
Param("T", "the type of value to compare").
ImportFunc(ByItself).
Source(`
{{ $compare := expand "CompareByItself" "T" (.T|elem) }}
return {{$compare}}(*val1, *val2)`)

ByItself.ImportFunc(comparePtr) 是为了避免循环引用自身而引入的。否则两个函数就会循环引用,导致编译失败。具有了这样的函数模板化的能力,我们可以把JSON编解码这样的复杂的utility也用模板的方式写出来。


泛型容器


除了支持模板函数之外,struct也可以加模板。写法如下:


var Pair = generic.DefineStruct("Pair").
Source(`
{{ $T1 := .I | method "First" | returnType }}
{{ $T2 := .I | method "Second" | returnType }}

type {{.structName}} struct {
first {{$T1|name}}
second {{$T2|name}}
}

func (pair *{{.structName}}) SetFirst(val {{$T1|name}}) {
pair.first = val
}

func (pair *{{.structName}}) First() {{$T1|name}} {
return pair.first
}

func (pair *{{.structName}}) SetSecond(val {{$T2|name}}) {
pair.second = val
}

func (pair *{{.structName}}) Second() {{$T2|name}} {
return pair.second
}`)

其中固定了一个模板参数叫,I。这个是指模板struct需要实现的interface。比如,如果用<int,string>来展开struct,对应的interface应该是:


type IntStringPair interface {
First() int
SetFirst(val int)
Second() string
SetSecond(val string)
}

使用的代码需要用这个interface来创建pair的实例:


func init() {
generic.DynamicCompilationEnabled = true
}

func Test_pair(t *testing.T) {
type IntStringPair interface {
First() int
SetFirst(val int)
Second() string
SetSecond(val string)
}
should := require.New(t)
intStringPairType := reflect.TypeOf(new(IntStringPair)).Elem()
pair := generic.New(Pair, intStringPairType).(IntStringPair)
should.Equal(0, pair.First())
pair.SetFirst(1)
should.Equal(1, pair.First())
}

go有没有有意思的且值的学习的开源项目推荐

woshicixide 回复了问题 • 2 人关注 • 2 个回复 • 444 次浏览 • 4 天前 • 来自相关话题

LiteIDE X31 发布,Go 语言开发工具

visualfc 发表了文章 • 1 个评论 • 677 次浏览 • 2017-03-03 08:33 • 来自相关话题

Go 语言开发工具 LiteIDE X31发布了。

新版本修复错误,优化了编辑体验。此版本增加了命令行支持重置用户设置,更新了文件向导功能,增加了空闲时文档自动保存功能,解决编辑器重载定位,重新恢复编辑工具栏,优化代码自动完成,增加大纲与编... 查看全部

Go 语言开发工具 LiteIDE X31发布了。


新版本修复错误,优化了编辑体验。此版本增加了命令行支持重置用户设置,更新了文件向导功能,增加了空闲时文档自动保存功能,解决编辑器重载定位,重新恢复编辑工具栏,优化代码自动完成,增加大纲与编辑器同步功能,修复macOS上目录同步错误和dlv加载问题等。此版本支持go1.8。


下载地址



更新记录



  • LiteIDE

    • add command line liteide [files|folder] [--select-env id] [--local-setting] [--user-setting] [--reset-setting]


  • LiteApp

    • add application idle timer automatic save documents option

    • folders are not sorted to resolve sync editing errors on MacOS

    • update new file wizard


  • GolangPackage

    • update GOPATH setup


  • GolangCode

    • update env load


  • GolangAst

    • classview and outline add sync editor action


  • DlvDebugger

    • fix dlv execution on MacOS


  • FakeVim

    • option add load default command list action


  • LiteEditor

    • fix editor restore vertical scrollbar postion

    • fix codecompleter prefix min setup

    • restore the editor toolbar

    • option add mimetype custom extsition setup


  • LiteBuild

    • build config xml file enable custom $() on cmd and args


TiDB Weekly [2017.02.13]

qiuyesuifeng 发表了文章 • 0 个评论 • 249 次浏览 • 2017-02-18 13:54 • 来自相关话题

Weekly update in TiDB

Last two weeks, we landed 查看全部

Weekly update in TiDB


Last two weeks, we landed 25 PRs in the TiDB repositories.


Added



Fixed



Improved



Weekly update in TiKV


Last week, We landed 14 PRs in the TiKV repositories.


Added



Fixed



Improved



原文链接

TiDB Weekly [2017.02.05]

qiuyesuifeng 发表了文章 • 0 个评论 • 201 次浏览 • 2017-02-18 13:52 • 来自相关话题

Weekly update in TiDB

Last two weeks, we landed 查看全部

Weekly update in TiDB


Last two weeks, we landed 43 PRs in the TiDB repositories.


Added



Fixed



Improved



Weekly update in TiKV


Last two weeks, we landed 20 PRs in the TiKV repositories.


Added



Fixed



Improved



原文链接

好玩的github项目-用go做个flappy bird

wwdyy 发表了文章 • 1 个评论 • 549 次浏览 • 2017-02-06 22:46 • 来自相关话题

flappy gopher

转自github用户neomede

A flappy bird clone made in go. 查看全部

flappy gopher


转自github用户neomede


A flappy bird clone made in go.


Based on this video and this project by Francesc Campoy, also this project by Sab


Play


Just run "make run" and use any button to jump


github地址:https://github.com/neomede/flappy

TiDB Weekly [2017.01.24]

qiuyesuifeng 发表了文章 • 0 个评论 • 293 次浏览 • 2017-02-04 11:43 • 来自相关话题

Weekly update in TiDB

Last two weeks, we landed 查看全部

Weekly update in TiDB


Last two weeks, we landed 87 PRs in the TiDB repositories.


Added



Fixed



Improved



New contributor



Weekly update in TiKV


Last two weeks, We landed 50 PRs in the TiKV repositories.


Added



Fixed



Improved



原文链接

TiDB Weekly [2017.01.08]

qiuyesuifeng 发表了文章 • 0 个评论 • 221 次浏览 • 2017-02-04 11:42 • 来自相关话题

Weekly update in TiDB

Last week, we landed 查看全部

Weekly update in TiDB


Last week, we landed 38 PRs in the TiDB repositories.


Added



Fixed



Improved



New contributor



Weekly update in TiKV


Last week, We landed 15 PRs in the TiKV repositories.


Added



Fixed



  • Check cluseter ID to avoid PD joining different cluster.


Improved



原文链接

TiDB Weekly [2017.01.01]

qiuyesuifeng 发表了文章 • 0 个评论 • 271 次浏览 • 2017-01-07 13:13 • 来自相关话题

Weekly update in TiDB

Last week, we landed 查看全部

Weekly update in TiDB


Last week, we landed 28 PRs in the TiDB repositories.


Added



Fixed



Improved



New contributor



Weekly update in TiKV


Last week, We landed 19 PRs in the TiKV repositories.


Added




  • Move raw_get to thread pool.




  • Add ResourceKind for operator and don't resend duplicated AddPeer response when the peer is still pending, see #449.



  • Add member command for pd-ctl.


Fixed



Improved



原文链接

TiDB Weekly [2016.12.26]

qiuyesuifeng 发表了文章 • 0 个评论 • 234 次浏览 • 2017-01-07 13:12 • 来自相关话题

New Release

TiDB RC1 is released!

Weekly updat... 查看全部

New Release


TiDB RC1 is released!


Weekly update in TiDB


Last week, we landed 34 PRs in the TiDB repositories.


Added



Fixed



Improved



New contributor



Weekly update in TiKV


Last week, We landed 14 PRs in the TiKV repositories.


Added



Fixed



Improved



原文链接

TiDB Weekly [2016.12.19]

qiuyesuifeng 发表了文章 • 0 个评论 • 280 次浏览 • 2016-12-25 13:46 • 来自相关话题

Weekly update in TiDB

Last week, we landed 查看全部

Weekly update in TiDB


Last week, we landed 32 PRs in the TiDB repositories.


Added



Fixed



Improved



New contributor



Weekly update in TiKV


Last week, we landed 11 PRs in the TiKV repositories.


Added



Fixed



Improved



原文链接

TiDB Weekly [2016.12.12]

qiuyesuifeng 发表了文章 • 0 个评论 • 318 次浏览 • 2016-12-17 14:14 • 来自相关话题

Weekly update in TiDB

Last week, we landed 查看全部

Weekly update in TiDB


Last week, we landed 41 PRs in the TiDB repositories.


Added



Fixed



Improved



Weekly update in TiKV


Last week, we landed 34 PRs in the TiKV repositories.


Added



Fixed



Improved



原文链接

好玩的github项目-可快速拉取各种网站的妹子图coll-mz

wwdyy 发表了文章 • 0 个评论 • 378 次浏览 • 2016-12-09 08:17 • 来自相关话题

转自github用户:fotomxq

collmz

介绍

COLL-MZ项目主要用于采集煎蛋、飞G、妹子图、Xiuren网站,以及本地类似图片、视频等文件,并展示到浏览器中。

特别申明查看全部

转自github用户:fotomxq


collmz


介绍


COLL-MZ项目主要用于采集煎蛋、飞G、妹子图、Xiuren网站,以及本地类似图片、视频等文件,并展示到浏览器中。


特别申明


该项目主要是个人学习golang而开发的第一个试水程序,请勿将该项目用于非法用途。


特点


专为闷骚程序员提供;
采集各大妹子图片数据;
手动采集、定时采集(2小时进行一次);
在浏览器快速浏览相关采集数据;
可整理本地文件、视频、漫画、文本等数据;
sqlite3开放式数据库,可自行构建访问,方便二次开发;
可根据具体需求,构建其他网站的采集程序;
纯Golang实现。


使用方法


1、下载项目到本地任意文件;


2、运行collmz-server-..exe文件;


3、通过浏览器访问http://localhost:8888可以看到项目,可在./config/config.json文件内自行修改端口。


4、初始用户名:admin@admin.com,密码:adminadmin


代码编译环境搭建步骤


1、安装golang语言运行环境,配置好环境变量;


2、安装gcc编译环境,并配置好环境变量,推荐使用mingw,下载地址:https://sourceforge.net/projects/mingw-w64/


3、安装golang第三方库:



  • goquery


github.com/PuerkitoBio/goquery



  • sqlite3


github.com/mattn/go-sqlite3



  • session


github.com/gorilla/sessions


4、下载该项目代码,到golang工作目录中任意目录,建议使用git克隆。


5、因为是在win10 x64下开发、编译的,所以只能保证该环境下运行良好,其他环境请自行排错。


FAQ


1、可以不部署代码直接使用么?


可以,下载整个项目,之后运行exe文件即可。项目内的controller文件夹可自行删除。


2、编译失败是什么情况?


常见的错误主要出在sqlite3上,因为该第三方库是用C实现的,需要用到GCC编译器,也就是mingw,所以如果安装错版本、没有配置对环境变量,都会报错。64位系统一定要使用64位的GCC编译。


3、想在此结构上构建其他采集器怎么做?


在controller下有coll-children-...go的文件,这些文件都是对应的采集器代码,可参考这些代码写自己需要的采集项目。


可使用构建好的相关框架,首先在coll.go内注册好采集器,这样可直接通过浏览器访问到采集器;然后自行建立go文件写入代码,这样就可以了。


注意,如果是正在开发的项目,CollChildren.dev尽量等于true,这样在浏览器端内容易区分。


CollOperate.Auto...(),这几个方法是集成了大部分情况下采集工作,可以极大方便采集工作。


关于项目逻辑、思维导图



4、采集速度如何?


由于sqlite3无法多开线程,所以一个采集器只能对应一个并发操作,如果发现重复运行、在采集过程中浏览数据会自动阻止。


每个采集器有各自的线程。


5、为什么某些采集器不能用?


个别采集器因为国内局域网限制,需要自行解决问题。


其次极个别采集的网站存在JS动态加载功能,以及各种阻拦采集工作的功能,所以未来看个人开发能力提升后再解决。这类采集器都标记了dev状态,你可以在采集界面中看到。


6、如何修改初始用户名和密码?


在写这段文本的时候,我才想起来没有做这个页面,所以暂时请用sqlite工具打开./content/database/coll-mz.sqlite数据库,修改其中的user表数据即可。




===============================================================
github地址:https://github.com/fotomxq/coll-mz

govpr,基于golang实现的gmm-ubm算法的说话人识别(声纹识别)引擎

ponpon_ 发表了文章 • 1 个评论 • 624 次浏览 • 2016-11-24 09:36 • 来自相关话题

再次推下自己的开源项目 govpr,基于golang实现的gmm-ubm算法的说话人识别(声纹识别)引擎,后续考虑推出java版本,c/c++版本,甚至是swift版本。gmm-ubm在声纹识别上已经是比较落后的算法了,完全没法跟现在的i-vector对... 查看全部

再次推下自己的开源项目 govpr,基于golang实现的gmm-ubm算法的说话人识别(声纹识别)引擎,后续考虑推出java版本,c/c++版本,甚至是swift版本。gmm-ubm在声纹识别上已经是比较落后的算法了,完全没法跟现在的i-vector对比,但是gmm-ubm仍然是基础,也是声纹识别入门的重中之重。如果条件允许,也有可能用go再去写一些i-vector算法,甚至是DNN算法的语音识别开源项目。


进入主题:


简介


govpr是golang 实现的基于 GMM-UBM 说话人识别引擎(声纹识别),可用于语音验证,身份识别的场景.
目前暂时仅支持汉语数字的语音,语音格式为wav格式(比特率16000,16bits,单声道)


安装


go get github.com/liuxp0827/govpr


示例


如下是一个简单的示例. 可跳转至 example
查看详细的例子,示例中的语音为纯数字8位数字.语音验证后得到一个得分,可设置阈值来判断验证语音是否为注册训练者本人.


package main

import (
"github.com/liuxp0827/govpr"
"github.com/liuxp0827/govpr/log"
"github.com/liuxp0827/govpr/waveIO"
"io/ioutil"
)

type engine struct {
vprEngine *govpr.VPREngine
}

func NewEngine(sampleRate, delSilRange int, ubmFile, userModelFile string) *engine {
return &engine{
vprEngine: govpr.NewVPREngine(sampleRate, delSilRange, ubmFile, userModelFile),
}
}

func (this *engine) DestroyEngine() {
this.vprEngine = nil
}

func (this *engine) TrainSpeech(buffers [][]byte) error {

var err error
count := len(buffers)
for i := 0; i < count; i++ {
err = this.vprEngine.AddTrainBuffer(buffers[i])
if err != nil {
log.Error(err)
return err
}
}

defer this.vprEngine.ClearTrainBuffer()
defer this.vprEngine.ClearAllBuffer()

err = this.vprEngine.TrainModel()
if err != nil {
log.Error(err)
return err
}

return nil
}

func (this *engine) RecSpeech(buffer []byte) error {

err := this.vprEngine.AddVerifyBuffer(buffer)
defer this.vprEngine.ClearVerifyBuffer()
if err != nil {
log.Error(err)
return err
}

err = this.vprEngine.VerifyModel()
if err != nil {
log.Error(err)
return err
}

Score := this.vprEngine.GetScore()
log.Infof("vpr score: %f", Score)
return nil
}

func main() {
log.SetLevel(log.LevelDebug)

vprEngine := NewEngine(16000, 50, "../ubm/ubm", "model/test.dat")
trainlist := []string{
"wav/train/01_32468975.wav",
"wav/train/02_58769423.wav",
"wav/train/03_59682734.wav",
"wav/train/04_64958273.wav",
"wav/train/05_65432978.wav",
}

trainBuffer := make([][]byte, 0)

for _, file := range trainlist {
buf, err := loadWaveData(file)
if err != nil {
log.Error(err)
return
}
trainBuffer = append(trainBuffer, buf)
}

verifyBuffer, err := waveIO.WaveLoad("wav/verify/34986527.wav")
if err != nil {
log.Error(err)
return
}

vprEngine.TrainSpeech(trainBuffer)
vprEngine.RecSpeech(verifyBuffer)
}

func loadWaveData(file string) ([]byte, error) {
data, err := ioutil.ReadFile(file)
if err != nil {
return nil, err
}
// remove .wav header info 44 bits
data = data[44:]
return data, nil
}

前几天已上传基于beego和mysql简单实现的httpapi,功能实现比较仓促所以很戳,有空再优化哈,顺便详细写写文档~~

TiDB Weekly [2016.11.21]

qiuyesuifeng 发表了文章 • 0 个评论 • 285 次浏览 • 2016-11-21 19:20 • 来自相关话题

Weekly update in TiDB

Last week, we landed 查看全部

Weekly update in TiDB


Last week, we landed 30 PRs in the TiDB repositories, 3 PRs in the TiDB docs repositories.


Added



Fixed



Improved



Document change


Add the following new guides:



Weekly update in TiKV


Last week, we landed 19 PRs in the TiKV repositories.


Fixed



Improved



原文链接