英文:
How to read an slice of like []interface{} in Go?
问题
我有这样的代码:
a := []interface{}{}
b := []interface{}{}
type S struct {
text string
}
s := S{"string"}
t := S{"string"}
a = append(a, s)
b = append(b, t)
a := append(a, b)
a
现在我想读取a的元素,或者元素的元素...但是怎么做呢?
英文:
I have something like this:
a := []interface{}{}
b := []interface{}{}
type S struct {
text string
}
s := S{"string"}
t := S{"string"}
a = append(a, s)
b = append(b, t)
a := append(a, b)
a
And now I want to read elements of a, or elements of elements.. but how?
答案1
得分: 4
你想要的是称为类型断言的东西。http://golang.org/ref/spec#Type_assertions
该页面上的简单示例是:
var x interface{} = 7 // x 的动态类型是 int,值为 7
i := x.(int) // i 的类型是 int,值为 7
另一个需要注意的是,类型断言会返回一个名为 ok
的值,如果断言成功,则为 true。以下是你的情况的一个简单代码示例:
a := []interface{}{}
b := []interface{}{}
type S struct {
text string
}
s := S{"string"}
t := S{"string"}
a = append(a, s)
b = append(b, t)
a = append(a, b)
assertedS, ok := a[0].(S)
if !ok { // 如果实际上不是 S 类型的值,那么就有问题
// 错误处理
}
fmt.Println(assertedS) // 应该显示与打印 s 相同的内容
assertedB, ok := a[1].([]interface{})
if !ok {
//...
}
assertedT, ok := assertedB[0].(S)
if !ok {
//...
}
fmt.Println(assertedT) // 应该显示与打印 t 相同的内容
如果事先不知道列表元素的类型,可以遍历它并使用 "类型开关"。http://golang.org/ref/spec#Switch_statements
switch x.(type) {
// cases
}
这允许你根据存储的 interface{} 的实际类型执行条件行为。
例如,你可以使用以下代码:
func ExtractSlice(a []interface{}) {
for _, x := range a {
switch i := x.(type) {
case S:
fmt.Println(i)
case []interface{}:
ExtractSlice(i) // 递归地解包 b,一旦在 a 中找到它
}
}
}
英文:
What you want is called a type assertion. http://golang.org/ref/spec#Type_assertions
The simple example on that page is:
var x interface{} = 7 // x has dynamic type int and value 7
i := x.(int) // i has type int and value 7`
The other thing to note is that a type assertion returns a value called ok
that is true if the assertion is successful. Here's a simple code example for your case:
a := []interface{}{}
b := []interface{}{}
type S struct {
text string
}
s := S{"string"}
t := S{"string"}
a = append(a, s)
b = append(b, t)
a = append(a, b)
assertedS,ok := a[0].(S)
if !ok { // If this is, in fact, not a value of type S, something is wrong
// error handling
}
fmt.Println(assertedS) // Should show you the same thing as printing s
assertedB,ok := a[1].([]interface{})
if !ok {
//...
}
assertedT,ok := assertedB[0].(S)
if !ok {
//...
}
fmt.Println(assertedT) // Should show you the same thing as printing t
If you don't know ahead of time which list element is what, you can iterate through it and use the "type switch". http://golang.org/ref/spec#Switch_statements
switch x.(type) {
// cases
}
Which allows you to perform conditional behavior based on what type the stored interface{} really is.
For instance, you might use
func ExtractSlice(a []interface{}) {
for _,x := range a {
switch i := x.(type) {
case S:
fmt.Println(i)
case []interface{}:
ExtractSlice(i) // Recursively unpacks b once it's found within a
}
}
}
答案2
得分: 2
你是指这个吗?
a := []interface{}{}
b := []interface{}{}
type S struct {
text string
}
s := S{"string"}
t := S{"string"}
a = append(a, s)
b = append(b, t)
a = append(a, b)
for _, v := range a {
switch v.(type) {
case S:
fmt.Println("S", v)
default:
fmt.Println("Slice", v)
}
}
英文:
Do you mean this?
a := []interface{}{}
b := []interface{}{}
type S struct {
text string
}
s := S{"string"}
t := S{"string"}
a = append(a, s)
b = append(b, t)
a = append(a, b)
for _, v := range a {
switch v.(type) {
case S:
fmt.Println("S", v)
default:
fmt.Println("Slice", v)
}
}
答案3
得分: 0
这是一个可能有帮助的代码示例:
package main
import "fmt"
func main() {
a := []interface{}{}
b := []interface{}{}
type S struct {
text string
}
s := S{"string s"}
t := S{"string t"}
a = append(a, s)
b = append(b, t)
a = append(a, b)
for _, v := range a {
fmt.Println(v)
}
}
但请注意,你将a
和b
定义为接口的切片。这意味着,当你执行a = append(a, b)
时,你将b
切片放在a
切片中现有的字符串之后,因此当你对a
进行range
循环时,你会得到:
{string s} // 字符串的接口
[{string t}] // 字符串接口的切片
英文:
This code example may help:
package main
import "fmt"
func main() {
a := []interface{}{}
b := []interface{}{}
type S struct {
text string
}
s := S{"string s"}
t := S{"string t"}
a = append(a, s)
b = append(b, t)
a = append(a, b)
for _, v := range a {
fmt.Println(v)
}
}
but be aware that you've defined a
and b
as slices of interfaces. This means, that when you do a = append(a, b)
you're putting the b
slice after the existing a
string in the a
slice, and therefore when you range
over a
you get:
>{string s} //interface of string
[{string t}] //slice of interface of string
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论