E
E
elfuegobiz2021-08-23 01:26:00
go
elfuegobiz, 2021-08-23 01:26:00

Why do we need generics, if it can be simpler?

Who is in the subject, please explain why in golang it is impossible to []something lead to []interface{} :

func remove(slice []interface{}, s interface{}) []interface{} {
    return append(slice[:s], slice[s+1:]...)
}

a := []string{"a", "b", "c"}
b := []int{1, 2, 3}

a = remove(a, 2)
b = remove(b, 1)


Here is a broader example. If you uncomment the last 2 lines in main(), then the program simply won't build. Question: why?? After all, I can pass a variable of type i1 to intf type parameters, why can't []i1 be passed to []intf parameter? I mean, why not make it possible. It would be much simpler in the sense that the issue of generics would not be so acute.

package main

import (
  "fmt"
  "strconv"
)

type intf interface {
  get() string
}

type i1 string

func (s i1) get() string {
  return string(s)
}

type i2 int

func (s i2) get() string {
  return strconv.Itoa(int(s))
}

func print1(a []intf) {
  for _, i := range a {
    fmt.Print(i, "; ")
  }
}

func main() {
  a := []intf{i1("xyz"), i2(42)}
  print1(a)
  //b := []i1{i1("xyz")}
  //print1(b)
}

Answer the question

In order to leave comments, you need to log in

3 answer(s)
S
Sergey Tikhonov, 2021-08-23
@elfuegobiz

Go sucks at interface algebra. Just because a struct A implements an interface I does not mean that []A implements []I.
And all because type casting to an interface is a manipulation with a type identifier in a structure. Obviously, you need to replace this identifier in the loop in each element of the slice in order to achieve the desired effect. I would like it to be inlined or somehow processed automatically during compilation, but not yet.

A
Alexey〒., 2021-08-23
@axifive

Who is in the subject, please explain why in golang it is impossible to []cast something to []interface{} :

You can bring it, but you have to do it yourself. interface{}it is a separate type and can only accept a slice of that type.slice []interface{}
func remove(slice []interface{}, s interface{}) []interface{} {
    return append(slice[:s.(int)], slice[s.(int)+1:]...)
}

func main() {
  a := []string{"a", "b", "c"}
  // преобразование
  ai := make([]interface{}, len(a))
  for i, v := range a {
    ai[i] = v
  }
  ai = remove(ai, 2)

  b := []int{1, 2, 3}
  // преобразование
  bi := make([]interface{}, len(b))
  for i, v := range b {
    bi[i] = v
  }
  bi = remove(bi, 1)
        
  fmt.Printf("%T: %v\n", ai, ai)
  fmt.Printf("%T: %v\n", bi, bi)
}

https://play.golang.org/p/gRHqO31LIJU
I mean, why not make it possible.

Because this is an array of arrays of type byte , and an array of numbers of type int and they have different memory representations . Same story:s []stringi []int
func main() {
  b := []i1{i1("xyz")}
  bi := make([]intf, len(b))
  for i, v := range b {
     bi[i] = v
  }
  print1(bi)
}

https://play.golang.org/p/z9BoM5lutV0

I
index0h, 2021-08-23
@index0h

Why do we need generics, if it can be simpler?

generics have nothing to do with it.
In essence, you are trying to pass to print1 (in the commented code) a slice of a different type. Yes, the element type of the slice matches your intf interface, but the slice itself does not. The next call is perfectly valid, but you can't do that with the i1 and i2 types.
func main() {
  print1([]intf{nil, nil})
}

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question