golang – how to get element from the interface{} type of slice?

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

golang - how to get element from the interface{} type of slice?

问题

我想编写一个函数,可以将切片([]int、[]string、[]bool、[]int64、[]float64)转换为字符串。

[]string{a,b,c} -> a,b,c
[]int{1,2,3} -> 1,2,3

以下是我的代码:

func sliceToString(itr interface{}) string {
    switch itr.(type) {
    case []string:
        return strings.Join(itr.([]string), ",")
    case []int:
        s := []string{}
        for _, v := range itr.([]int) {
            s = append(s, fmt.Sprintf("%v", v))
        }
        return strings.Join(s, ",")
    case []int64:
        s := []string{}
        for _, v := range itr.([]int64) {
            s = append(s, fmt.Sprintf("%v", v))
        }
        return strings.Join(s, ",")
    case []float64:
        s := []string{}
        for _, v := range itr.([]float64) {
            s = append(s, fmt.Sprintf("%v", v))
        }
        return strings.Join(s, ",")
    case []bool:
        s := []string{}
        for _, v := range itr.([]bool) {
            s = append(s, fmt.Sprintf("%v", v))
        }
        return strings.Join(s, ",")
    }

    return ""
}

但这有点复杂,如果我可以将interface{}(类型为切片)转换为[]interface{}或获取元素,就会更简单。

func sliceToString(itr interface{}) string {
    s := []string{}
    // 将interface{}转换为[]interface{}或获取元素
    // els := ...
    for _, v := range els {
        s = append(s, fmt.Sprintf("%v", v))
    }
    return strings.Join(s, ",")
}
英文:

I want to write a function that can convert slice([]int, []string, []bool, []int64, []float64) to string.

[]string{a,b,c} -> a,b,c
[]int{1,2,3}    -> 1,2,3

There is my code:

func sliceToString(itr interface{}) string {
	switch itr.(type) {
	case []string:
		return strings.Join(itr.([]string), ",")
	case []int:
		s := []string{}
		for _, v := range itr.([]int) {
			s = append(s, fmt.Sprintf("%v", v))
		}
		return strings.Join(s, ",")
	case []int64:
		s := []string{}
		for _, v := range itr.([]int64) {
			s = append(s, fmt.Sprintf("%v", v))
		}
		return strings.Join(s, ",")
	case []float64:
		s := []string{}
		for _, v := range itr.([]float64) {
			s = append(s, fmt.Sprintf("%v", v))
		}
		return strings.Join(s, ",")
	case []bool:
		s := []string{}
		for _, v := range itr.([]bool) {
			s = append(s, fmt.Sprintf("%v", v))
		}
		return strings.Join(s, ",")
	}

	return ""
}

But it's a little complicated, if i can convert interface{}(type is slice) to []interface{} or get element , it's getting more simple.

 func sliceToString(itr interface{}) string {
    s := []string{}
    // convert interface{} to []interface{} or get elements
    // els := ...
    for _,v:= range els{
       s = append(s, fmt.Sprintf("%v", v))
    }
    return s
 }

答案1

得分: 1

你不能这样做,因为int、string或其他任何类型的切片不能直接转换为接口类型的切片(请参考这个问题以获取更多解释)。

要进行转换,你需要将切片中的每个元素分别转换为interface{}类型。而且在没有先将切片转换为接口类型之前,你无法访问其中的元素,但是为了这样做,你需要知道切片的类型(所以我们又回到了起点)。

简化语法的一种方法是接受一个接口类型的切片作为参数,并让调用者进行转换(因为调用者知道切片的类型)。这里有一个示例:https://play.golang.org/p/6yLYk1OM25

package main

import (
	"fmt"
	"strings"
)

func main() {
	mySlice := []int{1, 2, 3}

	interfaceSlice := make([]interface{}, len(mySlice))
	for index := range mySlice {
		interfaceSlice[index] = mySlice[index]
	}

	fmt.Println(sliceToString(interfaceSlice))
}

func sliceToString(values []interface{}) string {
	s := make([]string, len(values)) // 预先分配正确的大小
	for index := range values {
		s[index] = fmt.Sprintf("%v", values[index])
	}
	return strings.Join(s, ",")
}

这将适用于任何类型的切片作为mySlice,但在这个过程中,你失去了调用者的很多便利性。

英文:

You can't do that, because a slice of int, string or anything can't be directly casted to a slice of interfaces. (see that question for more explanation on this).

To do the conversion, you need to cast each item of the slice as an interface{} separately. And you can't access the items without casting to a slice first, but for that you need to know the slice's type (so we're back to square one).

One way to shorten your syntax is to take in a slice of interfaces as argument, and let the caller do the conversion (because the caller knows the slice's type). Here is an example : https://play.golang.org/p/6yLYk1OM25

package main

import (
	"fmt"
	"strings"
)

func main() {
	mySlice := []int{1, 2, 3}

	interfaceSlice := make([]interface{}, len(mySlice))
	for index := range mySlice {
		interfaceSlice[index] = mySlice[index]
	}

	fmt.Println(sliceToString(interfaceSlice))
}

func sliceToString(values []interface{}) string {
	s := make([]string, len(values)) // Pre-allocate the right size
	for index := range values {
		s[index] = fmt.Sprintf("%v", values[index])
	}
	return strings.Join(s, ",")
}

This will work with any slice as mySlice, but on the way you lose a lot of convenience for the caller.

huangapple
  • 本文由 发表于 2015年10月10日 11:27:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/33049931.html
匿名

发表评论

匿名网友

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

确定