您现在的位置是:亿华云 > 系统运维
Go泛型草案设计简明指南
亿华云2025-10-04 04:07:51【系统运维】3人已围观
简介女主宣言今天小编为大家分享一篇关于Golang泛型提案的最新设计草案。涉及有关为何做出某些决策的详细信息,实施细节等。希望能对大家有所帮助。PS:丰富的一线技术、多元化的表现形式,尽在“360云计算”
女主宣言
今天小编为大家分享一篇关于Golang泛型提案的泛型最新设计草案。涉及有关为何做出某些决策的草案详细信息,实施细节等。设计希望能对大家有所帮助。简明
PS:丰富的指南一线技术、多元化的泛型表现形式,尽在“360云计算”,草案点关注哦!设计
最近,简明go团队宣布了针对其go泛型提案的指南最新设计草案。涉及有关为何做出某些决策的泛型详细信息,实施细节等。草案
因为整个草案设计内容太多了,设计所以本文中,简明我们的指南目标是总结即将进行的主要更改。
我们将提供一些代码片段来演示主要功能。
1
泛型函数中的类型约束
不受类型参数限制的通用函数:
// package decls, imports...func arrayOf(type T)(elems ...T) []T{
arr := []T{ }
for _, el := rangeelems {
arr = append(arr, el)
}
returnarr
}
func main(){
strs := arrayOf("one", "two", "three", "four", "five")
fmt.Println(strs)
nums := arrayOf(1, 2, 3, 4, 5)
fmt.Println(nums)
}
要对通用类型添加约束,可以要求实现给定的接口:
// package decls, imports...// Person, who implements fmt.Stringer...func join(type T fmt.Stringer)(tokens []T, delim string) string{
res := "" for _, token := rangetokens {
if res != ""{
res += delim
}
res += token.String()
}
returnres
}
func main(){
joined := join([]Person{ Person{ "Mike", "Jordan"}, Person{ "Dave", "Stevens"}, Person{ "John", "Doe"}}, ", ")
fmt.Println(joined)
}
要指定多个类型参数,用逗号分隔:
// package decls, imports...func mapAll(type T, R)(arr []T, mapFunc func(T) R) []R{
res := []R{ }
for _, el := rangearr {
res = append(res, mapFunc(el))
}
returnres
}
func main(){
strs := mapAll([]int{ 1, 2, 3}, func(n int) string{
returnstrconv.Itoa(n)
})
fmt.Println(strs)
}
对多个类型参数的云南idc服务商约束,与编写函数参数类型相同的方式写入:
// package decls, imports...// Person & Animal structs, which implement fmt.Stringer...func Concat(type T1, T2 fmt.Stringer)(f T1, s T2, delim string) string{
returnf.String() + delim + s.String()
}
func main(){
res := Concat(Person{ "John", "Doe"}, Animal{ "Dog", "Richie"}, " loves his ")
fmt.Println(res)
}
以下是为两个参数指定不同类型的方法:
// package decls, imports...// Hooman & Pet interfaces...// Person & Dog structs...func PlayAround(type H Hooman, P Pet)(human H, pet P){
fmt.Println("The human says:", human.Speak())
fmt.Println("And the pet responds:", pet.ProduceSound())
}
func main(){
PlayAround(Person{ }, Dog{ })
}2
类型列表及可比较
可以基于一组受支持的类型来约束它们,而不是基于一组方法来约束类型。例如,可以指定接受通用类型,该通用类型只能是int或long。
这能够 利用“小于”,“大于”之类的运算符,仅适用于Go中的基本类型:
// package decls, imports...// Ordered is a type constraint that matches any ordered type.// An ordered type is one that supports the <, <=, >, and >= operators.type Ordered interface{
type int, int8, int16, int32, int64,
uint, uint8, uint16, uint32, uint64, uintptr,
float32, float64,
string}
func Max(type T Ordered)(elems []T) T{
if len(elems) == 0{
varzero T
returnzero
}
max := elems[0]
for _, el := rangeelems {
ifel > max {
max = el
}
}
returnmax
}
func main(){
res := Max([]int{ 1, 5, 3, 10, 4})
fmt.Println(res)
}
还具有一个称为“comparable”的现成约束,该约束类型与支持==和!=运算符的约束类型相同。
// package decls, imports...func Contains(type T comparable)(elems []T, target T) bool{
for _, elem := rangeelems {
ifelem == target {
return true}
}
return false}
func main(){
fmt.Println(Contains([]int{ 1, 2, 3, 4, 5}, 4))
}
使用这些构造的接口-类型列表和/或类似列表只能用作类型约束,而不能用作函数参数。
3
通用类型
可以使用泛型类型定义结构。一旦指定了类型声明,就无需为该类型的所有函数指定类型:
// package decls, imports...type Stack(type T) struct{
buffer []T
}
func (v *Stack(T)) Push(elem T){
v.buffer = append(v.buffer, elem)
}
func (v *Stack(T)) Pop() T{
res := v.buffer[len(v.buffer)-1]
v.buffer = v.buffer[:len(v.buffer)-1]
returnres
}
func main(){
st := &Stack(int){ }
st.Push(1)
st.Push(2)
st.Push(3)
fmt.Println(st.Pop())
fmt.Println(st.Pop())
fmt.Println(st.Pop())
}
也可以在接口中执行此操作。当类型约束依赖于自身时,这尤其有用。
例如。源码下载有一个T的类型约束,它需要一个Equal方法,该方法接受一个T参数:
// package decls, imports...// Person, who implements Equaler...type Equaler(type T) interface{
Equal(other T) bool}
func Contains(type T Equaler)(elems []T, target T) bool{
for _, elem := rangeelems {
ifelem.Equal(target) {
return true}
}
return false}
func main(){
people := []Person{ Person{ "Dave"}, Person{ "Bob"}, Person{ "Steve"}}
fmt.Println(Contains(people, Person{ "Dave"}))
}
如果需要指定具有状态修改功能的类型参数(例如,setter),则可以指定指针类型约束:
// package decls, imports...type Setter interface{
Set(string)
}
type Settable int// Set sets the value of *p from a string.func (p *Settable) Set(s string){
i, _ := strconv.Atoi(s)
*p = Settable(i)
}
func FromStrings(type *T Setter)(s []string) []T{
result := make([]T, len(s))
for i, v := ranges {
// result[i] is an addressable value of type T, // so its OK to call Set.result[i].Set(v)
}
returnresult
}
func main(){
nums := FromStrings(Settable)([]string{ "1", "2", "3"})
fmt.Println(nums)
}
注意,上面的示例如何要求明确指定将在函数中使用的类型– FromStrings(Settable)…
这是因为只要类型不作为函数参数出现,编译代码后,编译器就无法推断实际类型。因此,需要明确指定它。
总结
本文的目的是简洁明了。希望它可以帮助大家快速了解最新的泛型草案设计。
但是,围绕Go中的泛型进行任何单一设计选择,背后都有很多理由。如果有兴趣深入研究该主题,可以查阅官方设计草案文档。
很赞哦!(3)
站长推荐
4、企业无形资产:通用网站已成为企业网络知识产权的重要组成部分,属于企业的无形资产,也有助于提升企业的品牌形象和技术领先形象。它是企业品牌资产不可或缺的一部分。
多机房多活架构,到底有多牛?
拯救DBA!美团SQL解析探索实践
异步编程还得看JDK8
用户邮箱的静态密码可能已被钓鱼和同一密码泄露。在没有收到安全警报的情况下,用户在适当的时间内不能更改密码。在此期间,攻击者可以随意输入帐户。启用辅助身份验证后,如果攻击者无法获取移动电话动态密码,他将无法进行身份验证。这样,除非用户的电子邮件密码和手机同时被盗,否则攻击者很难破解用户的邮箱。
Oracle系统数据复制技术?这里为你详解一下~
如何使用 JavaScript 开发者控制台
我们一起聊聊指针与函数