为什么在Go中需要泛型?


本文是关于向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, , , :

  • .
  • .
  • map.
  • .
  • map' , map.

. , , ++.

, Go .

  • .
  • .
  • , .
  • Context, , .

, . Go. , .

, . , . , , , .

Go - : map. , , . , . , []int, , , .

map' — - , . :

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

Source: https://habr.com/ru/post/zh-CN462811/


All Articles