本文是关于向Go添加泛型的含义,以及为什么我认为我们应该这样做。 我还将介绍语言体系结构的可能变化,以添加泛型。
Go于2009年11月10日发布。 不到一天后,
关于仿制药的
第一条评论出现了 。 它还提到了一些例外情况,我们以恐慌的形式添加了该语言,并于2010年初恢复。
经过三年的观察,缺少泛型一直是该语言中需要解决的三个主要问题的清单。
为什么需要泛型?
添加泛型是什么意思,为什么我们要它?
释义
Jazayeri和其他人 :使用泛型编程可让您将函数和数据结构表示为泛型,但不包括类型。
这是什么意思?
假设我们需要以相反的顺序表示切片的元素。 这不是一个很常见的任务,但也不是那么罕见。
假设我们有一个整数切片。
func ReverseInts(s []int) {
first := 0
last := len(s)
for first < last {
s[first], s[last] = s[last], s[first]
first++
last--
}
}
. . , . , .
func ReverseInts(s []int) {
first := 0
last := len(s) - 1
for first < last {
s[first], s[last] = s[last], s[first]
first++
last--
}
}
1,
last
. .
func ReverseStrings(s []string) {
first := 0
last := len(s) - 1
for first < last {
s[first], s[last] = s[last], s[first]
first++
last--
}
}
ReverseInts
ReverseStrings
, , , . .
Go,
Reverse
, .
.
Python JavaScript . Go , , .
, ++, Java, Rust Swift, .
Go
Go?
, (interface type) , .
sort.Sort
.
, Go — . . , , , .
. . . , , , , , - , . — , , .
, , , - . Go , , , ,
Index
, . , , . -, , map' . Go , . .
-
Reverse
, reflect, . , .
,
Reverse
. . ,
Reverse
, - , , .
, , , Go, . , , , , . .
, , , , . , . , Go . .
Go . , . .
Go
, Go,
Reverse
. . , Go .
open source, , -
Reverse
, .
, «» . «» , . , , ++, , .
Reverse
, , , :
. , , ++.
, Go .
, . Go. , .
, . , . , , , .
Go - : map. , , . , . ,
[]int
, , , .
map' — - , . :
-, , , , map: , , , .
, , - .
,
Reverse
: - , , , . map, , , , .
Go . , .
, , .
Big Rock Candy Mountain, ,
. . , Go . , .
Go , , . , , , . .
, , .
. , .
-,, -. , . , -, - , . -.
- , . , , , . , .
Go. C . .
Go, Go . Go . . , , - .
Go. : , , Go .
, . , , Go.
Gophercon (Robert Griesemer)
Go. , .
Reverse
.
func Reverse (type Element) (s []Element) {
first := 0
last := len(s) - 1
for first < last {
s[first], s[last] = s[last], s[first]
first++
last--
}
}
, .
.
Element
(type parameter). , , , .
, , , .
func ReverseAndPrint(s []int) {
Reverse(int)(s)
fmt.Println(s)
}
(int)
,
Reverse
.
, , , , .
- .
func ReverseAndPrint(s []int) {
Reverse(s)
fmt.Println(s)
}
-
Reverse
ReverseInts
ReverseStrings
, , .
Go , .
, -, - .
Reverse
.
Element
, Go. -, , .
.
func IndexByte (type T Sequence) (s T, b byte) int {
for i := 0; i < len(s); i++ {
if s[i] == b {
return i
}
}
return -1
}
bytes strings
IndexByte
.
b
s
,
s
[]byte
. - bytes strings. , .
,
T
—
[]byte
.
len
, byte.
T
. , , - ,
T
.
Sequence
. .
Sequence
.
contract Sequence(T) {
T string, []byte
}
, :
T
[]byte
. , . .
,
, Gophercon 2018, , . , , . , .
/ . .
,
String
[]string
s
.
func ToStrings (type E Stringer) (s []E) []string {
r := make([]string, len(s))
for i, v := range s {
r[i] = v.String()
}
return r
}
: ,
String
.
,
String
.
Stringer
.
contract Stringer(T) {
T String() string
}
,
T
String
.
,
fmt.Stringer
, ,
ToStrings
fmt.Stringer
. - ,
fmt.Stringer
.
fmt.Stringer
, Go . ,
fmt.Stringer
.
.
type Graph (type Node, Edge G) struct { ... }
contract G(Node, Edge) {
Node Edges() []Edge
Edge Nodes() (from Node, to Node)
}
func New (type Node, Edge G) (nodes []Node) *Graph(Node, Edge) {
...
}
func (g *Graph(Node, Edge)) ShortestPath(from, to Node) []Edge {
...
}
, . . ,
Node
Edges
, ,
Node
.
Edge
Nodes
,
Nodes
,
Edge
.
,
New
,
Graph
,
ShortestPath
Graph
.
, - . .
(Ordered types)
Go
Min
. ,
Max
. ,
Min
, .
Min
, . :
func Min (type T Ordered) (a, b T) T {
if a < b {
return a
}
return b
}
Ordered
,
T
, « », « », .
contract Ordered(T) {
T int, int8, int16, int32, int64,
uint, uint8, uint16, uint32, uint64, uintptr,
float32, float64,
string
}
Ordered
— , . , , - . , « ».
, « », , . , Go .
, , , -, . , -, , . - , , .
, , .
Min
(, , ) .
Ordered
, .
func Min (type T contracts.Ordered) (a, b T) T {
if a < b {
return a
}
return b
}
-
, - , . , .
type Tree (type E) struct {
root *node(E)
compare func(E, E) int
}
type node (type E) struct {
val E
left, right *node(E)
}
.
New
.
func New (type E) (cmp func(E, E) int) *Tree(E) {
return &Tree(E){compare: cmp}
}
,
v
, , .
func (t *Tree(E)) find(v E) **node(E) {
pn := &t.root
for *pn != nil {
switch cmp := t.compare(v, (*pn).val); {
case cmp < 0:
pn = &(*pn).left
case cmp > 0:
pn = &(*pn).right
default:
return pn
}
}
return pn
}
, , . , - .
, .
func (t *Tree(E)) Contains(v E) bool {
return *t.find(e) != nil
}
This is the code for inserting a new value.
func (t *Tree(E)) Insert(v E) bool {
pn := t.find(v)
if *pn != nil {
return false
}
*pn = &node(E){val: v}
return true
}
E
. - . , Go, , .
.
var intTree = tree.New(func(a, b int) int { return a - b })
func InsertAndCheck(v int) {
intTree.Insert(v)
if !intTree.Contains(v) {
log.Fatalf("%d not found after insertion", v)
}
}
. - , . -- .
, . , , , . , , .
CL, go/types. , , , . , , .
, -, , . , , . , , - . , .
, , , Go. . , .
— , -, , Go. , — , , , , . , - Go.