Go泛型草案设计简明指南

发布时间:2025-05-23 10:42:10 作者:益华网络 来源:undefined 浏览量(0) 点赞(0)
摘要:女主宣言 今天小编为大家分享一篇关于Golang泛型提案的最新设计草案。涉及有关为何做出某些决策的详细信息,实施细节等。希望能对大家有所帮助。 PS:丰富的一线技术、多元化的表现形式,尽在“360云计算”,点关注哦! 最

女主宣言

今天小编为大家分享一篇关于Golang泛型提案的最新设计草案。涉及有关为何做出某些决策的详细信息,实施细节等。希望能对大家有所帮助。

PS:丰富的一线技术、多元化的表现形式,尽在“360云计算”,点关注哦!

最近,go团队宣布了针对其go泛型提案的最新设计草案。涉及有关为何做出某些决策的详细信息,实施细节等。

因为整个草案设计内容太多了,所以本文中,我们的目标是总结即将进行的主要更改。

我们将提供一些代码片段来演示主要功能。

1

泛型函数中的类型约束

不受类型参数限制的通用函数:

// package decls, imports...func arrayOf(type T)(elems ...T) []T

{

 arr := []T{}

 for _, el := range

elems {

   arr = append

(arr, el)

 }

 return

arr

}

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 := range

tokens {

   if res != ""

{

     res += delim

   }

   res += token.String()

 }

 return

res

}

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 := range

arr {

   res = append

(res, mapFunc(el))

 }

 return

res

}

func main()

{

 strs := mapAll([]int{1, 2, 3}, func(n int) string

{

   return

strconv.Itoa(n)

 })

 fmt.Println(strs)

}

对多个类型参数的约束,与编写函数参数类型相同的方式写入:

// package decls, imports...// Person & Animal structs, which implement fmt.Stringer...func Concat(type T1, T2 fmt.Stringer)(f T1, s T2, delim string) string

{

 return

f.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

{

   var

zero T

   return

zero

 }

 max := elems[0

]

 for _, el := range

elems {

   if

el > max {

     max = el

   }

 }

 return

max

}

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 := range

elems {

   if

elem == 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

]

 return

res

}

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 := range

elems {

   if

elem.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 := range

s {

   // result[i] is an addressable value of type T,    // so its OK to call Set.

   result[i].Set(v)

 }

 return

result

}

func main()

{

 nums := FromStrings(Settable)([]string{"1", "2", "3"

})

 fmt.Println(nums)

}

注意,上面的示例如何要求明确指定将在函数中使用的类型– FromStrings(Settable)…

这是因为只要类型不作为函数参数出现,编译代码后,编译器就无法推断实际类型。因此,需要明确指定它。

本文的目的是简洁明了。希望它可以帮助大家快速了解最新的泛型草案设计。

但是,围绕Go中的泛型进行任何单一设计选择,背后都有很多理由。如果有兴趣深入研究该主题,可以查阅官方设计草案文档。

二维码

扫一扫,关注我们

声明:本文由【益华网络】编辑上传发布,转载此文章须经作者同意,并请附上出处【益华网络】及本页链接。如内容、图片有任何版权问题,请联系我们进行处理。

感兴趣吗?

欢迎联系我们,我们愿意为您解答任何有关网站疑难问题!

您身边的【网站建设专家】

搜索千万次不如咨询1次

主营项目:网站建设,手机网站,响应式网站,SEO优化,小程序开发,公众号系统,软件开发等

立即咨询 15368564009
在线客服
嘿,我来帮您!