英文:
How to check if interface{} is a slice
问题
我是Go的新手 所以我的问题可能很愚蠢,但是找不到答案,所以。
我需要一个函数:
func name (v interface{}) {
if is_slice() {
for _, i := range v {
my_var := i.(MyInterface)
... 做一些事情
}
} else {
my_var := v.(MyInterface)
... 做一些事情
}
}
在Go中如何实现is_slice
?感谢任何帮助。
英文:
I'm noob in Go so my question may be stupid, but can't find answer, so.
I need a function:
func name (v interface{}) {
if is_slice() {
for _, i := range v {
my_var := i.(MyInterface)
... do smth
}
} else {
my_var := v.(MyInterface)
... do smth
}
}
How can I do is_slice
in Go? Appreciate any help.
答案1
得分: 16
is_slice
方法可以像这样:
func IsSlice(v interface{}) bool {
return reflect.TypeOf(v).Kind() == reflect.Slice
}
如果需要的话,还可以添加额外的条件reflect.TypeOf(v).Kind() == reflect.Array
。
英文:
The is_slice
method can be something like this:
func IsSlice(v interface{}) bool {
return reflect.TypeOf(v).Kind() == reflect.Slice
}
Can also put additional condition of reflect.TypeOf(v).Kind() == reflect.Array
if required.
答案2
得分: 15
在你的情况下,类型开关是最简单和最方便的解决方案:
func name(v interface{}) {
switch x := v.(type) {
case []MyInterface:
fmt.Println("[]MyInterface, len:", len(x))
for _, i := range x {
fmt.Println(i)
}
case MyInterface:
fmt.Println("MyInterface:", x)
default:
fmt.Printf("不支持的类型:%T\n", x)
}
}
case
分支列举了可能的类型,在其中 x
变量将已经是该类型,因此你可以使用它。
测试一下:
type MyInterface interface {
io.Writer
}
var i MyInterface = os.Stdout
name(i)
var s = []MyInterface{i, i}
name(s)
name("something else")
输出结果(在 Go Playground 上尝试):
MyInterface: &{0x1040e110}
[]MyInterface, len: 2
&{0x1040e110}
&{0x1040e110}
不支持的类型:string
对于单个类型检查,你还可以使用 类型断言:
if x, ok := v.([]MyInterface); ok {
// x 是类型 []MyInterface
for _, i := range x {
fmt.Println(i)
}
} else {
// x 不是类型 []MyInterface 或者为 nil
}
还有其他方法,使用 reflect
包 可以编写一个更通用(但更慢)的解决方案,但如果你刚开始学习 Go,不应该深入研究反射。
英文:
In your case the type switch is the simplest and most convenient solution:
func name(v interface{}) {
switch x := v.(type) {
case []MyInterface:
fmt.Println("[]MyInterface, len:", len(x))
for _, i := range x {
fmt.Println(i)
}
case MyInterface:
fmt.Println("MyInterface:", x)
default:
fmt.Printf("Unsupported type: %T\n", x)
}
}
The case
branches enumerate the possible types, and inside them the x
variable will already be of that type, so you can use it so.
Testing it:
type MyInterface interface {
io.Writer
}
var i MyInterface = os.Stdout
name(i)
var s = []MyInterface{i, i}
name(s)
name("something else")
Output (try it on the Go Playground):
MyInterface: &{0x1040e110}
[]MyInterface, len: 2
&{0x1040e110}
&{0x1040e110}
Unsupported type: string
For a single type check you may also use type assertion:
if x, ok := v.([]MyInterface); ok {
// x is of type []MyInterface
for _, i := range x {
fmt.Println(i)
}
} else {
// x is not of type []MyInterface or it is nil
}
There are also other ways, using package reflect
you can write a more general (and slower) solution, but if you're just starting Go, you shouldn't dig into reflection yet.
答案3
得分: 3
> interface{} 什么都不表示
一个更好的方法可能是为每种类型定义一个函数:
func name(v MyInterface) {
// 做一些操作
}
func names(vs []MyInterface) {
for _, v := range(vs) {
name(v)
}
}
英文:
icza's answer is correct, but is not recommended by go creators:
> interface{} says nothing
A better approach may be to define a function for each type you have:
func name(v MyInterface) {
// do something
}
func names(vs []MyInterface) {
for _, v := range(vs) {
name(v)
}
}
答案4
得分: 0
从 https://blog.golang.org/json
解码任意数据
考虑以下 JSON 数据,存储在变量 b 中:
b := []byte(`{"Name":"Wednesday","Age":6,"Parents":["Gomez","Morticia"]}`)
在不知道该数据结构的情况下,我们可以使用 Unmarshal 将其解码为 interface{} 值:
var f interface{}
err := json.Unmarshal(b, &f)
此时,f 中的 Go 值将是一个键为字符串、值为空接口值的映射:
f = map[string]interface{}{
"Name": "Wednesday",
"Age": 6,
"Parents": []interface{}{
"Gomez",
"Morticia",
},
}
要访问这些数据,我们可以使用类型断言来访问 f 的底层 map[string]interface{}:
m := f.(map[string]interface{})
然后,我们可以使用 range 语句遍历该映射,并使用类型开关来访问其值的具体类型:
for k, v := range m {
switch vv := v.(type) {
case string:
fmt.Println(k, "是字符串", vv)
case float64:
fmt.Println(k, "是 float64", vv)
case []interface{}:
fmt.Println(k, "是一个数组:")
for i, u := range vv {
fmt.Println(i, u)
}
default:
fmt.Println(k, "是一个我不知道如何处理的类型")
}
}
通过这种方式,您可以处理未知的 JSON 数据,同时仍然享受类型安全的好处。
英文:
From https://blog.golang.org/json
Decoding arbitrary data
Consider this JSON data, stored in the variable b:
b := []byte(`{"Name":"Wednesday","Age":6,"Parents":["Gomez","Morticia"]}`)
Without knowing this data's structure, we can decode it into an interface{} value with Unmarshal:
var f interface{}
err := json.Unmarshal(b, &f)
At this point the Go value in f would be a map whose keys are strings and whose values are themselves stored as empty interface values:
f = map[string]interface{}{
"Name": "Wednesday",
"Age": 6,
"Parents": []interface{}{
"Gomez",
"Morticia",
},
}
To access this data we can use a type assertion to access f's underlying map[string]interface{}:
m := f.(map[string]interface{})
We can then iterate through the map with a range statement and use a type switch to access its values as their concrete types:
for k, v := range m {
switch vv := v.(type) {
case string:
fmt.Println(k, "is string", vv)
case float64:
fmt.Println(k, "is float64", vv)
case []interface{}:
fmt.Println(k, "is an array:")
for i, u := range vv {
fmt.Println(i, u)
}
default:
fmt.Println(k, "is of a type I don't know how to handle")
}
}
In this way you can work with unknown JSON data while still enjoying the benefits of type safety.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论