生成模板代码实现Golang泛型

生成模板代码实现Golang泛型

Golang是强类型静态语言,暂不支持泛型。那么如何定义通用类型的数据结构和算法呢?使用interface{}不是好的解决方案,接口需要转换同时会丢失静态类型的优势。本文我们介绍模板代码结合代码生成器,实现编译时检查、安全的、高性能的泛型编程。

1. 实现通用Set数据结构

如何实现一个数据结构(算法也一样)支持常用类型,生成特定类型实现,可以轻松重用。

使用genny,非常简单几个步骤:

  1. 导入genny/generic
  2. 定义类型为通用类型generic.Type,例如,命令为ItemType
  3. 在代码中使用这些通用类型
  4. 运行genny生成类型实现

下面实现比较简单的Set数据结构,定义ItemSet泛型Set,同时定义了Add和Clean方法:

//go:generate genny -in=$GOFILE -out=gen-$GOFILE gen "Item=string,int"

package set

import "github.com/cheekybits/genny/generic"

// Item the type of the Set
type Item generic.Type

// ItemSet the set of Items
type ItemSet struct {
	items map[Item]bool
}

func (s *ItemSet)Add(t Item) ItemSet  {
	if s.items == nil {
		s.items = make(map[Item]bool)
	}

	_, ok := s.items[t]
	if !ok {
		s.items[t] = true
	}

	return *s
}

func (s *ItemSet) Clean(){
	s.items = make(map[Item]bool)
}

当然需要先使用go get -u github.com/cheekybits/genny 命令安装genny,编译通过后。运行命令:
genny -in set.go -out gen-set.go gen "Item=string,int"

命令执行之后,如果输入文件为set.go,则会生成gen-set.go

// This file was automatically generated by genny.
// Any changes will be lost if this file is regenerated.
// see https://github.com/cheekybits/genny

// Package Set creates a StringSet data structure for the string type
package set

// StringSet the set of Strings
type StringSet struct {
	items map[string]bool
}

// Add adds a new element to the Set. Returns the Set.
func (s *StringSet) Add(t string) StringSet {
	s.items[t] = true
	return *s
}

// Clear removes all elements from the Set
func (s *StringSet) Clear() {
	(*s).items = make(map[string]bool)
}

// Delete removes the string from the Set and returns Has(string)
func (s *StringSet) Delete(item string) bool {
	ret := (*s).Has(item)
	if ret {
		delete((*s).items, item)
	}
	return ret
}

// Has returns true if the Set contains the string
func (s *StringSet) Has(item string) bool {
	return (*s).items[item]
}

// Strings returns the string(s) stored
func (s *StringSet) Strings() []string {
	items := []string{}
	for i := range s.items {
		items = append(items, i)
	}
	return items
}

// Package Set creates a IntSet data structure for the int type

// IntSet the set of Ints
type IntSet struct {
	items map[int]bool
}

// Add adds a new element to the Set. Returns the Set.
func (s *IntSet) Add(t int) IntSet {
	s.items[t] = true
	return *s
}

// Clear removes all elements from the Set
func (s *IntSet) Clear() {
	(*s).items = make(map[int]bool)
}

// Delete removes the int from the Set and returns Has(int)
func (s *IntSet) Delete(item int) bool {
	ret := (*s).Has(item)
	if ret {
		delete((*s).items, item)
	}
	return ret
}

// Has returns true if the Set contains the int
func (s *IntSet) Has(item int) bool {
	return (*s).items[item]
}

// Ints returns the int(s) stored
func (s *IntSet) Ints() []int {
	items := []int{}
	for i := range s.items {
		items = append(items, i)
	}
	return items
}

我们看到genny帮我们从ItemSet **生成了StringSetIntSet结构,因为Item=string,int

同时也生成对应结构体方法,如果你想增加其他类型,只要编辑命令重新运行。

2. 使用 go generate

我们也可以通过在文件的顶部,包文档注释的下面增加go generate注释:

//go:generate genny -in=$GOFILE -out=gen-$GOFILE gen "Item=string,int"

命令指定使用genny,同时需要翻译Item为string和int。接着直接在源文件目录下运行下面命令:

go generate

同样会生成gen-set.go文件,包括string和int类型结构体。

重要:上面通用实现的数据结构可以像go generate生成的具体实现一样,进行编译和测试,因此可以针对通用或特定类型的实现运行测试。

3. 总结

本文介绍了利用gennygo generate生成代码,辅助实现泛型数据结构和算法。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值