How to create a slice of variable type in Go?

huangapple go评论142阅读模式
英文:

How to create a slice of variable type in Go?

问题

我有一个函数。

func doSome(v interface{}) {

}  

如果我通过指针将一个结构体切片传递给函数,函数必须填充该切片。

type Color struct {
}
type Brush struct {
}

var c []Color
doSome(&c) // 在执行后,c将包含3个Color类型的元素的数组

var b []Brush
doSome(&b) // 在执行后,b将包含3个Brush类型的元素的数组

也许我需要使用反射,但是如何使用呢?

英文:

I have a function.

func doSome(v interface{}) {

}  

If I pass by pointer a slice of struct into the function, the function must fill the slice.

type Color struct {
}
type Brush struct {
}

var c []Color
doSome(&c) // after с is array contains 3 elements type Color

var b []Brush
doSome(&b) // after b is array contains 3 elements type Brush

Maybe I need use reflection, but how?

答案1

得分: 4

func doSome(v interface{}) {

s := reflect.TypeOf(v).Elem()
slice := reflect.MakeSlice(s, 3, 3)
reflect.ValueOf(v).Elem().Set(slice)

}

将上述代码翻译为中文如下:

func doSome(v interface{}) {

    s := reflect.TypeOf(v).Elem()
    slice := reflect.MakeSlice(s, 3, 3)
    reflect.ValueOf(v).Elem().Set(slice)

}

将上述代码翻译为中文如下:

func doSome(v interface{}) {

    s := reflect.TypeOf(v).Elem()
    slice := reflect.MakeSlice(s, 3, 3)
    reflect.ValueOf(v).Elem().Set(slice)

}
英文:
func doSome(v interface{}) {

    s := reflect.TypeOf(v).Elem()
    slice := reflect.MakeSlice(s, 3, 3)
    reflect.ValueOf(v).Elem().Set(slice)

}  

答案2

得分: 3

typeswitch!!

package main
import "fmt"

func doSome(v interface{}) {
  switch v := v.(type) {
  case *[]Color:
    *v = []Color{Color{0}, Color{128}, Color{255}}
  case *[]Brush:
    *v = []Brush{Brush{true}, Brush{true}, Brush{false}}
  default:
    panic("unsupported doSome input")
  }
}  

type Color struct {
	r uint8
}
type Brush struct {
	round bool
}

func main(){
	var c []Color
	doSome(&c) // after c is array contains 3 elements type Color

	var b []Brush
	doSome(&b) // after b is array contains 3 elements type Brush

	fmt.Println(b)
	fmt.Println(c)
	
}
类型切换!!

package main
import "fmt"

func doSome(v interface{}) {
  switch v := v.(type) {
  case *[]Color:
    *v = []Color{Color{0}, Color{128}, Color{255}}
  case *[]Brush:
    *v = []Brush{Brush{true}, Brush{true}, Brush{false}}
  default:
    panic("不支持的 doSome 输入")
  }
}  

type Color struct {
	r uint8
}
type Brush struct {
	round bool
}

func main(){
	var c []Color
	doSome(&c) // c 现在是包含 3 个 Color 类型元素的数组

	var b []Brush
	doSome(&b) // b 现在是包含 3 个 Brush 类型元素的数组

	fmt.Println(b)
	fmt.Println(c)
	
}

这是一个Go语言的代码示例,它展示了类型切换的用法。在函数doSome中,根据传入参数的类型进行不同的操作。如果传入的是*[]Color类型的指针,则将其指向的数组修改为包含三个Color类型的元素;如果传入的是*[]Brush类型的指针,则将其指向的数组修改为包含三个Brush类型的元素。如果传入的类型不是以上两种类型,则会抛出一个错误。

main函数中,首先定义了两个空数组cb,然后分别调用doSome函数对它们进行处理。最后,打印出数组bc的内容。

希望对你有帮助!如果有任何其他问题,请随时问我。

英文:

typeswitch!!

package main
import "fmt"

func doSome(v interface{}) {
  switch v := v.(type) {
  case *[]Color:
    *v = []Color{Color{0}, Color{128}, Color{255}}
  case *[]Brush:
    *v = []Brush{Brush{true}, Brush{true}, Brush{false}}
  default:
    panic("unsupported doSome input")
  }
}  

type Color struct {
	r uint8
}
type Brush struct {
	round bool
}

func main(){
	var c []Color
	doSome(&c) // after с is array contains 3 elements type Color

	var b []Brush
	doSome(&b) // after b is array contains 3 elements type Brush

	fmt.Println(b)
	fmt.Println(c)
	
}

答案3

得分: 1

Go语言没有泛型。你有以下几种选择:

  1. 接口分派
type CanTraverse interface {
    Get(int) interface{}
    Len() int
}

type Colours []Colour

func (c Colours) Get(i int) interface{} {
    return c[i]
}

func (c Colours) Len() int {
    return len(c)
}

func doSome(v CanTraverse) {
    for i := 0; i < v.Len(); i++ {
        fmt.Println(v.Get(i))
    }
}
  1. 类型切换(如@Plato所建议)
func doSome(v interface{}) {
    switch v := v.(type) {
    case *[]Colour:
        // 处理颜色
    case *[]Brush:
        // 处理画笔
    default:
        panic("不支持的doSome输入")
    }
}
  1. 反射(类似于fmt.Println()的方式)。反射非常强大,但也非常耗费资源,可能会导致代码运行缓慢。以下是一个简单的示例:
func doSome(v interface{}) {
    value := reflect.ValueOf(v)
    if value.Kind() == reflect.Slice {
        for i := 0; i < value.Len(); i++ {
            element := value.Slice(i, i+1)
            fmt.Println(element)
        }
    } else {
        fmt.Println("这不是一个切片")
    }
}
英文:

Go has no generics. Your possibilities are:

Interface dispatching

type CanTraverse interface {
	Get(int) interface{}
	Len() int
}
type Colours []Colour

func (c Colours) Get(i int) interface{} {
	return c[i]
}
func (c Colours) Len() int {
	return len(c)
}
func doSome(v CanTraverse) {
	for i := 0; i &lt; v.Len; i++ {
		fmt.Println(v.Get(i))
	}
}

Type switch as @Plato suggested

func doSome(v interface{}) {
  switch v := v.(type) {
  case *[]Colour:
    //Do something with colours
  case *[]Brush:
    //Do something with brushes
  default:
    panic(&quot;unsupported doSome input&quot;)
  }
}

Reflection as fmt.Println() do. Reflection is very powerful but very expensive, code may be slow. Minimal example

func doSome(v interface{}) {
	value := reflect.ValueOf(v)
	if value.Kind() == reflect.Slice {
		for i := 0; i &lt; value.Len(); i++ {
			element := value.Slice(i, i+1)
			fmt.Println(element)
		}
	} else {
		fmt.Println(&quot;It&#39;s not a slice&quot;)
	}
}

huangapple
  • 本文由 发表于 2016年9月7日 15:30:51
  • 转载请务必保留本文链接:https://go.coder-hub.com/39363798.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定